mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-26 12:52:22 -08:00
Compare commits
4 Commits
hover-effe
...
cssUI
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3affe8c062 | ||
|
|
ce9644d83f | ||
|
|
36b0f9392c | ||
|
|
dda9f07cb4 |
6
.github/workflows/api_doc.yml
vendored
6
.github/workflows/api_doc.yml
vendored
@@ -4,10 +4,8 @@ name: Deploy static content to Pages
|
||||
on:
|
||||
# Runs on pushes targeting the default branch
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
branches:
|
||||
- develop
|
||||
branches: ["develop"]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
16
.github/workflows/codemeta_validator.yml
vendored
16
.github/workflows/codemeta_validator.yml
vendored
@@ -1,16 +0,0 @@
|
||||
name: test_codemeta
|
||||
|
||||
on:
|
||||
release:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: gitlab-registry.in2p3.fr/escape2020/wp3/eossr:v1.0
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: validate codemeta
|
||||
run: eossr-metadata-validator codemeta.json
|
||||
3
.github/workflows/npm-publish.yml
vendored
3
.github/workflows/npm-publish.yml
vendored
@@ -6,9 +6,6 @@ name: Publish to NPM
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,25 +1,7 @@
|
||||
# Changelogs
|
||||
|
||||
## 3.3.2
|
||||
|
||||
* [fixed] do not allow to query the properties several times for an imageHiPS
|
||||
* [fixed] Detecting raytracing rendering mode. Adapt the rendering mode in function of the fov value and the projection used. Some projections do have more distortions with wide FoVs so it is better to use the raytracing rendering mode when fov >= smaller FoV threshold.
|
||||
|
||||
## 3.3.0
|
||||
|
||||
* [fixed] multiple calls to setImageSurvey with the same survey object led to strange behaviour.
|
||||
* [perf] Display the first tile received instantly with no blending. Should enhance the slow reported in issue #88.
|
||||
* [fixed] A.on('select') (debugged from ipyaladin)
|
||||
* [fixed] Simbad pointer in galactical frame, cone search of simbad/vizier cats/other cone search services in galactical frame and MOC creation from selection in galactical frame => there is now a new `frame` optional param to Aladin.pix2world. If not given, the coo returned are in the frame of the view.
|
||||
* [doc] Add doc for image survey definition
|
||||
* [deprecation] A.createImageSurvey/A.newImageSurvey are now deprecated (but still in the API). Please use `A.imageHiPS` instead by providing a valid url or CDS ID conformed to <https://aladin.cds.unistra.fr/hips/list>
|
||||
* [refac] Simplify the instanciation of an imageHiPS/ imageFITS. Add a `A.imageHiPS` method for defining a HiPS object
|
||||
* [fixed] At initialisation, giving a fov > 180 was clamped back to 180 even if we specify allsky projection (i.e. accepting fov > 180). This is now fixed.
|
||||
* [fixed] MeasurementTable now display the full cell values (no ellipsis anymore)
|
||||
* [fixed] aladin.on('select') has been implemented. Callback is triggered on a circle and rect selections for not on polygonal selection.
|
||||
* [fixed] the cooFrame UI selector is updated if the user calls `aladin.setFrame`
|
||||
* [fixed] `reticleColor` and `reticleSize` options in the public API
|
||||
* Restore setFoVRange
|
||||
* Add CSS class for positioning the UI elements as the user wants. See the API doc aladin options for the class names to use.
|
||||
* [style] The default grid color is now `rgb(178, 50, 178)` to fit the classic Aladin color palette
|
||||
* [feat] The object of grid options `gridOptions` is now available in the public API
|
||||
|
||||
43
README.md
43
README.md
@@ -11,7 +11,6 @@ Aladin Lite is built to be easily embeddable in any web page. It powers astronom
|
||||
More details on [Aladin Lite documentation page](http://aladin.u-strasbg.fr/AladinLite/doc/).
|
||||
|
||||
[](https://github.com/cds-astro/aladin-lite/actions/workflows/test.yml)
|
||||
[](https://cds-astro.github.io/aladin-lite)
|
||||
|
||||
# How to test it ?
|
||||
|
||||
@@ -143,53 +142,33 @@ to compile the core project into WebAssembly.
|
||||
Follow the steps from the Rust official website [here](https://www.rust-lang.org/learn/get-started)
|
||||
You will also need [wasm-pack](https://rustwasm.github.io/wasm-pack/), a tool helping compiling rust into a proper .wasm file.
|
||||
|
||||
Once it's installed you will need to switch to the nightly rust version:
|
||||
|
||||
```bash
|
||||
rustup default nightly
|
||||
```
|
||||
|
||||
Then you can build the project:
|
||||
|
||||
Once it's installed you can only build the project:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
:warning: **If you are experimenting rust error compilations**:
|
||||
|
||||
- Make sure you have your **wasm-pack** version updated. To do so:
|
||||
|
||||
```bash
|
||||
cargo install wasm-pack --version ~0.12
|
||||
```
|
||||
|
||||
- Make sure you are using the rust **nightly** toolchain
|
||||
- Remove your `src/core/Cargo.lock` file and `src/core/target` directory -- this ensures that you'd escape any bad compilation state:
|
||||
|
||||
```bash
|
||||
git clean -di
|
||||
```
|
||||
|
||||
- then recompile with `npm run build`.
|
||||
|
||||
It will generate the aladin lite compiled code into a `dist/` directory located at the root of the repository. This directory contains two javascript files. `aladin.umd.cjs` follows the UMD module export convention and it is the one you can use for your project.
|
||||
|
||||
To run the examples, you can start a localhost server with the following command:
|
||||
|
||||
Or build it and launch a localhost server (usually starting on port 8080 but it can be another one if 8080 is occupied):
|
||||
```bash
|
||||
npm run serve
|
||||
```
|
||||
|
||||
For just compiling the rust core, from the root location do:
|
||||
For just compiling the rust core from the root location (it is faster to do so)
|
||||
|
||||
```bash
|
||||
cd src/core
|
||||
cargo check --features webgl2
|
||||
```
|
||||
|
||||
and run the tests:
|
||||
and run the tests
|
||||
|
||||
```bash
|
||||
cd src/core
|
||||
cargo test --features webgl2
|
||||
```
|
||||
|
||||
To generate the Rust backend API documentation
|
||||
|
||||
```bash
|
||||
cd src/core
|
||||
cargo doc --no-deps --open
|
||||
```
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><title>file_type_jupyter</title><path d="M26.233,3.588A1.69,1.69,0,1,1,24.473,2a1.67,1.67,0,0,1,1.76,1.585Z" style="fill:#767677"/><path d="M16.375,23.111c-4.487,0-8.43-1.61-10.469-3.988a11.162,11.162,0,0,0,20.938,0C24.81,21.5,20.882,23.111,16.375,23.111Z" style="fill:#f37726"/><path d="M16.375,7.648c4.487,0,8.43,1.61,10.469,3.988a11.162,11.162,0,0,0-20.938,0C7.945,9.253,11.869,7.648,16.375,7.648Z" style="fill:#f37726"/><path d="M10.2,27.739a2.109,2.109,0,1,1-.2-.8,2.129,2.129,0,0,1,.2.8Z" style="fill:#9e9e9e"/><path d="M6.416,7.106A1.226,1.226,0,1,1,7.608,5.83,1.241,1.241,0,0,1,6.416,7.106Z" style="fill:#616262"/></svg>
|
||||
|
Before Width: | Height: | Size: 836 B |
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.197 3.35462C16.8703 1.67483 19.4476 1.53865 20.9536 3.05046C22.4596 4.56228 22.3239 7.14956 20.6506 8.82935L18.2268 11.2626M10.0464 14C8.54044 12.4882 8.67609 9.90087 10.3494 8.22108L12.5 6.06212" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M13.9536 10C15.4596 11.5118 15.3239 14.0991 13.6506 15.7789L11.2268 18.2121L8.80299 20.6454C7.12969 22.3252 4.55237 22.4613 3.0464 20.9495C1.54043 19.4377 1.67609 16.8504 3.34939 15.1706L5.77323 12.7373" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 776 B |
@@ -1,83 +0,0 @@
|
||||
{
|
||||
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
|
||||
"@type": "SoftwareSourceCode",
|
||||
"license": "https://spdx.org/licenses/GPL-3.0",
|
||||
"codeRepository": "https://github.com/cds-astro/aladin-lite",
|
||||
"dateCreated": "2013-05-01",
|
||||
"datePublished": "2013-05-01",
|
||||
"dateModified": "2023-01-31",
|
||||
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
|
||||
"name": "Aladin Lite",
|
||||
"version": "3.3.2",
|
||||
"softwareVersion": "3.3.2",
|
||||
"description": "An astronomical HiPS visualizer in the browser.",
|
||||
"identifier": "10.5281/zenodo.7638833",
|
||||
"applicationCategory": "Astronomy, Visualization",
|
||||
"funding": "ESCAPE 824064",
|
||||
"referencePublication": "http://aspbooks.org/publications/532/007.pdf",
|
||||
"readme": "https://aladin.cds.unistra.fr/AladinLite/doc/",
|
||||
"releaseNotes": "https://aladin.cds.unistra.fr/AladinLite/doc/#release-notes",
|
||||
"funder": {
|
||||
"@type": "Organization",
|
||||
"name": "European Commission Framework Programme Horizon 2020 Research and Innovation action"
|
||||
},
|
||||
"keywords": [
|
||||
"IVOA",
|
||||
"Astronomy"
|
||||
],
|
||||
"programmingLanguage": [
|
||||
"Rust",
|
||||
"Javascript"
|
||||
],
|
||||
"relatedLink": [
|
||||
"https://aladin.cds.unistra.fr/"
|
||||
],
|
||||
"author": [
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0002-7123-773X",
|
||||
"givenName": "Matthieu",
|
||||
"familyName": "Baumann",
|
||||
"email": "matthieu.baumann@unistra.fr",
|
||||
"affiliation": {
|
||||
"@type": "Organization",
|
||||
"name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0001-5818-2781",
|
||||
"givenName": "Thomas",
|
||||
"familyName": "Boch",
|
||||
"email": "thomas.boch@astro.unistra.fr",
|
||||
"affiliation": {
|
||||
"@type": "Organization",
|
||||
"name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France"
|
||||
}
|
||||
}
|
||||
],
|
||||
"maintainer": [
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0002-7123-773X",
|
||||
"givenName": "Matthieu",
|
||||
"familyName": "Baumann",
|
||||
"email": "matthieu.baumann@unistra.fr",
|
||||
"affiliation": {
|
||||
"@type": "Organization",
|
||||
"name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France"
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Person",
|
||||
"@id": "https://orcid.org/0000-0001-5818-2781",
|
||||
"givenName": "Thomas",
|
||||
"familyName": "Boch",
|
||||
"email": "thomas.boch@astro.unistra.fr",
|
||||
"affiliation": {
|
||||
"@type": "Organization",
|
||||
"name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -20,12 +20,14 @@
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', cooFrame: 'galactic', fov: 360, fullScreen: true, showCooGrid: false, showReticle: false})
|
||||
aladin = A.aladin('#aladin-lite-div', {cooFrame: 'galactic', fov: 400, fullScreen: true, showCooGrid: false, showReticle: false})
|
||||
aladin.gotoRaDec(79.9525321, -69.2742586)
|
||||
const gaiaFlux = aladin.createImageSurvey('P/DM/flux-G/I/355/gaiadr3', "GaiaDR3GFlux", null, null, null, {imgFormat: 'fits', stretch: 'log'})
|
||||
aladin.setBaseImageLayer(gaiaFlux)
|
||||
gaiaFlux.setCuts(3e5, 1e8)
|
||||
|
||||
aladin.setProjection('MOL')
|
||||
|
||||
|
||||
|
||||
function notify(title, sub, delay) {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 70,projection: "AIT"});
|
||||
|
||||
let hsc = aladin.newImageSurvey("P/HSC/DR2/deep/g", {colormap:"Purples", imgFormat: "fits"});
|
||||
aladin.setBaseImageLayer(hsc);
|
||||
//let hsc = aladin.newImageSurvey("P/HSC/DR2/deep/g", {colormap:"Purples", imgFormat: "fits"});
|
||||
//aladin.setBaseImageLayer(hsc);
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {target: 'LMC', fov: 55, showContextMenu: true});
|
||||
var hips = A.catalogHiPS('https://axel.u-strasbg.fr/HiPSCatService/Simbad', {hoverColor: 'yellow', onClick: 'showPopup', name: 'Simbad'});
|
||||
var hips = A.catalogHiPS('https://axel.u-strasbg.fr/HiPSCatService/Simbad', {onClick: 'showPopup', name: 'Simbad'});
|
||||
aladin.addCatalog(hips);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -252,13 +252,13 @@
|
||||
aladin.addCatalog(hipsCats['constellations-boundaries']);
|
||||
aladin.addCatalog(hipsCats['gaia']);
|
||||
|
||||
var coronelliStars = {
|
||||
'coronelli-stars-white': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/white.xml", {name: 'Coronelli white', color: '#ffffff', shape: 'rhomb', sourceSize: 10}),
|
||||
'coronelli-stars-yellow': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/yellow.xml", {name: 'Coronelli yellow', color: '#f6f874', shape: 'rhomb', sourceSize: 10}),
|
||||
'coronelli-stars-red': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/red.xml", {name: 'Coronelli red', color: '#ff5555', shape: 'rhomb', sourceSize: 10}),
|
||||
'coronelli-stars-blue': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/blue.xml", {name: 'Coronelli blue', color: '#1ca5ec', shape: 'rhomb', sourceSize: 20})
|
||||
};
|
||||
|
||||
var coronelliStars = {
|
||||
'coronelli-stars-white': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/white.xml", {name: 'Coronelli white', color: '#ffffff', shape: 'rhomb', sourceSize: 10}),
|
||||
'coronelli-stars-yellow': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/yellow.xml", {name: 'Coronelli yellow', color: '#f6f874', shape: 'rhomb', sourceSize: 10}),
|
||||
'coronelli-stars-red': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/red.xml", {name: 'Coronelli red', color: '#ff5555', shape: 'rhomb', sourceSize: 10}),
|
||||
'coronelli-stars-blue': A.catalogFromURL("http://cdsweb.u-strasbg.fr/~derriere/coronelli/blue.xml", {name: 'Coronelli blue', color: '#1ca5ec', shape: 'rhomb', sourceSize: 10})
|
||||
};
|
||||
coronelliStars['coronelli-stars-white'].hide();
|
||||
coronelliStars['coronelli-stars-yellow'].hide();
|
||||
coronelliStars['coronelli-stars-red'].hide();
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
aladin.addStatusBarMessage({
|
||||
duration: 10000,
|
||||
type: 'info',
|
||||
message: 'Aladin Lite v3.3 is out. New features available:<ul><li>New Button, Box <b>objects</b></li><li>Polygonal, circular selection</li></ul>'
|
||||
message: 'Aladin Lite v3.3 is out. New features available:<ul><li>New Button, Box objects</li><li>Polygonal, circular selection</li></ul>'
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@@ -94,11 +94,6 @@
|
||||
|
||||
background-color: pink;
|
||||
}
|
||||
|
||||
.aladin-cooFrame {
|
||||
position: absolute;
|
||||
top: 10rem;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
}, // no optional params
|
||||
(ra, dec, fov, image) => {
|
||||
// ra, dec and fov are centered around the fits image
|
||||
console.log("jjj", image)
|
||||
image.setColormap("magma", {stretch: "asinh"});
|
||||
|
||||
aladin.gotoRaDec(ra, dec);
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
aladin.setBaseImageLayer("P/PanSTARRS/DR1/g", {imgFormat: "fits"});
|
||||
aladin.getBaseImageLayer().setColormap('redtemperature', {stretch: "Asinh"});*/
|
||||
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: 'CDS/P/SDSS9/color', fov: 150, target: '0 90', fullScreen: true, cooFrame: 'equatorial', showCooGridControl: true, showSimbadPointerControl: true, showCooGrid: true});
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: 'CDS/P/SDSS9/color', fov: 60, target: '0 90', fullScreen: true, cooFrame: 'equatorial', showCooGridControl: true, showSimbadPointerControl: true, showCooGrid: true});
|
||||
aladin.setProjection('SIN');
|
||||
|
||||
//let survey = aladin.createImageSurvey("P/PanSTARRS/DR1/g", null, null, null, null, );
|
||||
/*aladin.setBaseImageLayer("P/PanSTARRS/DR1/g");
|
||||
|
||||
@@ -16,14 +16,22 @@
|
||||
showContextMenu: true,
|
||||
fullScreen: true,
|
||||
showSimbadPointerControl: true,
|
||||
showSimbadPointerControl: false,
|
||||
showShareControl: true,
|
||||
showSettingsControl: true,
|
||||
showStatusBar: {
|
||||
position: {
|
||||
bottom: 0,
|
||||
left: '3rem'
|
||||
},
|
||||
},
|
||||
showStackLayerControl: true,
|
||||
samp: true,
|
||||
});
|
||||
|
||||
aladin.addCatalog(A.catalogFromSimbad('M 82', 0.1, {onClick: 'showTable'}));
|
||||
aladin.addCatalog(A.catalogFromNED('09 55 52.4 +69 40 47', 0.1, {onClick: 'showPopup', shape: 'plus'}));
|
||||
A.catalogFromSimbad('09 55 52.4 +69 40 47', 0.1, {onClick: 'showTable', limit: 1000}, (cat) => {
|
||||
aladin.addCatalog(cat)
|
||||
});
|
||||
aladin.addCatalog(A.catalogFromNED('09 55 52.4 +69 40 47', 0.1, {onClick: 'showPopup', shape: 'plus'}));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ A.init.then(() => {
|
||||
console.log(objs, "are selected");
|
||||
})
|
||||
|
||||
aladin.select();
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var overlay = A.graphicOverlay({color: '#ee2345', lineWidth: 3});
|
||||
aladin.addOverlay(overlay);
|
||||
overlay.addFootprints([
|
||||
A.polygon([[83.64287, 22.01713], [83.59872, 22.01692], [83.59852, 21.97629], [83.64295, 21.97629]], {hoverColor: 'green'}),
|
||||
A.polygon([[83.64287, 22.01713], [83.59872, 22.01692], [83.59852, 21.97629], [83.64295, 21.97629]]),
|
||||
A.polygon([[83.62807, 22.06330], [83.58397, 22.02280], [83.62792, 22.02258]]),
|
||||
A.polygon([[8.62807, 220.06330], [83.58397, 10.02280], [150.62792, 87.02258]])
|
||||
]);
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
var aladin = A.aladin(
|
||||
'#aladin-lite-div',
|
||||
{
|
||||
survey: 'P/allWISE/color', // set initial image survey
|
||||
projection: 'AIT', // set a projection
|
||||
fov: 1.5, // initial field of view in degrees
|
||||
target: 'NGC 2175', // initial target
|
||||
cooFrame: 'galactic', // set galactic frame
|
||||
reticleColor: '#00ff00', // change reticle color
|
||||
reticleSize: 40, // change reticle size
|
||||
gridOptions: {color: 'pink'},
|
||||
showCooGrid: true, // set the grid
|
||||
fullScreen: true,
|
||||
showShareControl: true,
|
||||
showSettingsControl: true,
|
||||
showLayersControl: true,
|
||||
showZoomControl: true,
|
||||
showContextMenu: true,
|
||||
showCooGridControl: true,
|
||||
showSimbadPointerControl: true,
|
||||
showFullscreenControl: true,
|
||||
}
|
||||
);
|
||||
|
||||
aladin.setFoVRange(1, 60)
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div id="offset" style="display: inline-block; width: 200px; height: 100px"></div>
|
||||
<div id="aladin-lite-div" style="display: inline-block; width: 50%"></div>
|
||||
</div>
|
||||
<!--<script type="text/javascript" src="https://aladin.cds.unistra.fr/AladinLite/api/v3/latest/aladin.js" charset="utf-8"></script>-->
|
||||
|
||||
|
||||
<script>let aladin, hips</script>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'TAN', cooFrame: 'galactic', showSettingsControl: true, showSimbadPointerControl: true, showContextMenu: true, target: 'galactic center', survey: 'P/Finkbeiner'});
|
||||
// possible values are 'blues', 'cividis', 'cubehelix', 'eosb', 'grayscale', 'inferno', 'magma', 'native', 'parula', 'plasma', 'rainbow',
|
||||
// 'rdbu', 'rdylbu', 'redtemperature', 'sinebow', 'spectral', 'summer', 'viridis', 'ylgnbu' and 'ylorbr'
|
||||
|
||||
//aladin.getBaseImageLayer().setColor([1.0, 0.0, 1.0, 1.0], { tf: 'Linear'} );
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,9 +13,9 @@
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: 'http://alasky.cds.unistra.fr/ancillary/GaiaDR2/hips-density-map/', showProjectionControl: true, showContextMenu: true, showStatusBar: true, fullScreen: true, target: 'galactic center'});
|
||||
|
||||
const fluxMap = aladin.createImageSurvey('gdr3-color-flux-map', 'Gaia DR3 flux map', 'https://alasky.u-strasbg.fr/ancillary/GaiaEDR3/color-Rp-G-Bp-flux-map', 'equatorial', 7);
|
||||
const densityMap = aladin.createImageSurvey('gdr3-density-map', 'Gaia DR3 density map', 'sdfsg', 'equatorial', 7, {formats: ['fits']});
|
||||
const decaps = aladin.createImageSurvey("decaps", "DECaPS DR1", "http://alasky.u-strasbg.fr/DECaPS/DR1/color/", "equatorial", 11, {formats: ['png'], tileSize: 512});
|
||||
const panstarrs = aladin.createImageSurvey("panstarrs", "PanSTARRS", "http://alasky.u-strasbg.fr/Pan-STARRS/DR1/color-i-r-g/", "equatorial", 11, {formats: ['jpg']});
|
||||
const densityMap = aladin.createImageSurvey('gdr3-density-map', 'Gaia DR3 density map', 'sdfsg', 'equatorial', 7, {imgFormat: 'fits'});
|
||||
const decaps = aladin.createImageSurvey("decaps", "DECaPS DR1", "http://alasky.u-strasbg.fr/DECaPS/DR1/color/", "equatorial", 11, {imgFormat: 'png'});
|
||||
const panstarrs = aladin.createImageSurvey("panstarrs", "PanSTARRS", "http://alasky.u-strasbg.fr/Pan-STARRS/DR1/color-i-r-g/", "equatorial", 11, {imgFormat: 'jpg'});
|
||||
|
||||
aladin.setOverlayImageLayer(fluxMap)
|
||||
aladin.setOverlayImageLayer(densityMap, "density")
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, height=device-height, maximum-scale=1.0, initial-scale=1.0, user-scalable=no">
|
||||
</head>
|
||||
<body>
|
||||
<div id="aladin-lite-div" style="width: 500px; height: 500px"></div>
|
||||
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
var aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, cooFrame: "ICRSd", showSimbadPointerControl: true, showShareControl: true, showShareControl: true, survey: 'https://alasky.cds.unistra.fr/DSS/DSSColor/', fov: 180, showContextMenu: true});
|
||||
// manage URL parameters
|
||||
let survey1 = aladin.getBaseImageLayer();
|
||||
survey1.setColormap('magma', {stretch: 'linear'});
|
||||
|
||||
let survey2 = aladin.newImageSurvey("CSIRO/P/RACS/mid/I");
|
||||
aladin.setImageLayer(survey2)
|
||||
survey2.setColormap('rdbu', {stretch: 'linear'});
|
||||
|
||||
let survey3 = aladin.newImageSurvey("CSIRO/P/RACS/low/I");
|
||||
aladin.setImageLayer(survey3)
|
||||
survey3.setColormap('cubehelix', {stretch: 'asinh'});
|
||||
aladin.setImageLayer(survey3)
|
||||
aladin.setImageLayer(survey3)
|
||||
|
||||
aladin.setImageLayer(survey2);
|
||||
|
||||
aladin.setImageLayer(survey3)
|
||||
aladin.setImageLayer(survey2);
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
@@ -10,7 +10,8 @@
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: 'P/allWISE/color', target: 'galactic center'});
|
||||
aladin = A.aladin('#aladin-lite-div', {target: 'galactic center'});
|
||||
aladin.setImageSurvey('P/allWISE/color');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
var aladin;
|
||||
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin(
|
||||
var aladin = A.aladin(
|
||||
'#aladin-lite-div',
|
||||
{
|
||||
survey: 'P/allWISE/color', // set initial image survey
|
||||
@@ -24,14 +23,13 @@
|
||||
gridOptions: {color: 'pink'},
|
||||
showCooGrid: true, // set the grid
|
||||
fullScreen: true,
|
||||
showStatusBar: false,
|
||||
showShareControl: true,
|
||||
showSettingsControl: true,
|
||||
showLayersControl: true,
|
||||
showZoomControl: true,
|
||||
showContextMenu: true,
|
||||
showCooGridControl: true,
|
||||
//showSimbadPointerControl: true,
|
||||
showSimbadPointerControl: true,
|
||||
showFullscreenControl: true,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
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: 3, perimeter: true}, (moc) => {
|
||||
var moc11 = A.MOCFromURL('http://skies.esac.esa.int/HST/NICMOS/Moc.fits', {color: '#84f', lineWidth: 3, fill: true}, (moc) => {
|
||||
// moc is ready
|
||||
console.log(moc.contains(205.9019247, +2.4492764));
|
||||
console.log(moc.contains(-205.9019247, +2.4492764));
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
<script>var aladin;</script>
|
||||
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', fullScreen: true, fov: 360, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: true, showSettingsControl: true, showCooGrid: true});
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: true, showCooGrid: true, fov: 180});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 70,projection: "AIT"});
|
||||
|
||||
aladin.setOverlayImageLayer(A.imageHiPS(
|
||||
'Fermi',
|
||||
"https://alasky.cds.unistra.fr/Fermi/Color",
|
||||
{
|
||||
name: "Fermi color",
|
||||
maxOrder: 3,
|
||||
imgFormat: 'jpeg',
|
||||
tileSize: 512,
|
||||
cooFrame: 'equatorial'
|
||||
}
|
||||
));
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,11 +12,11 @@
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {target: 'NGC 1367', fov: 360, samp: false, projection: 'AIT', fullScreen: true, showContextMenu: true});
|
||||
|
||||
A.catalogFromURL('https://raw.githubusercontent.com/VisIVOLab/SKA-Discovery-Service-Mockup/main/ObsCore/ObsCore_003.xml', {onClick: 'showTable', hoverColor: 'purple'}, (catalog) => {
|
||||
A.catalogFromURL('https://raw.githubusercontent.com/VisIVOLab/SKA-Discovery-Service-Mockup/main/ObsCore/ObsCore_003.xml', {onClick: 'showTable'}, (catalog) => {
|
||||
aladin.addCatalog(catalog)
|
||||
});
|
||||
|
||||
aladin.addCatalog(A.catalogFromVizieR("B/assocdata/obscore", "0 +0", 20, {limit: 1000, hoverColor: 'cyan'}))
|
||||
aladin.addCatalog(A.catalogFromVizieR("B/assocdata/obscore", "0 +0", 20, {limit: 1000}))
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
// Start up Aladin Lite
|
||||
aladin = A.aladin('#aladin-lite-div', {
|
||||
fov: 360,
|
||||
projection: 'MER',
|
||||
target: '0 0',
|
||||
fullScreen: true,
|
||||
survey: "CDS/P/Mars/Pan-Perseverance-PIA24422",
|
||||
showCooGrid: true,
|
||||
showCooGridControl: true,
|
||||
});
|
||||
|
||||
aladin.setProjection('MER');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,18 +6,14 @@
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
|
||||
<div id='aladin-statsDiv'></div>
|
||||
<script>let aladin, hips</script>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {cooFrame: 'galactic', target: 'galactic center', survey: 'P/Finkbeiner'});
|
||||
// possible values are 'blues', 'cividis', 'cubehelix', 'eosb', 'grayscale', 'inferno', 'magma', 'native', 'parula', 'plasma', 'rainbow',
|
||||
// 'rdbu', 'rdylbu', 'redtemperature', 'sinebow', 'spectral', 'summer', 'viridis', 'ylgnbu' and 'ylorbr'
|
||||
hips = aladin.getBaseImageLayer()
|
||||
hips.setColormap("cubehelix");
|
||||
|
||||
aladin.setImageSurvey('astron.nl/P/lotss_dr2_high')
|
||||
|
||||
aladin.getBaseImageLayer().setColormap("cubehelix");
|
||||
//aladin.getBaseImageLayer().setColor([1.0, 0.0, 1.0, 1.0], { tf: 'Linear'} );
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-1.10.1.min.js"></script>
|
||||
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
|
||||
Show sources with proper motion greater than:
|
||||
<input id='slider' style='vertical-align:middle;width:60vw;' step='1' min='0' max='10' type='range' value='0'>
|
||||
<span id='pmVal' >0 mas/yr</span><br><br><div id='aladin-lite-div' style='width: 500px;height: 500px;'></div>
|
||||
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
var colorThreshold = 0;
|
||||
var slider = document.getElementById('slider');
|
||||
slider.oninput = function() {
|
||||
colorThreshold = this.value;
|
||||
$('#colorVal').html(colorThreshold);
|
||||
cat.reportChange();
|
||||
}
|
||||
var myFilterFunction = function(source) {
|
||||
const magB = parseFloat(source.data['B']);
|
||||
const magV = parseFloat(source.data['V']);
|
||||
if (isNaN(magB) || isNaN(magV) ) {
|
||||
return false;
|
||||
}
|
||||
const color = magB - magV;
|
||||
return color>colorThreshold;
|
||||
}
|
||||
|
||||
aladin = A.aladin('#aladin-lite-div', {target: 'M 81', fov: 0.5, survey: 'CDS/P/SDSS9/color'});
|
||||
var cat = A.catalogFromSimbad('M 81', 0.25, {onClick: 'showTable', verbosity: 3, filter: myFilterFunction});
|
||||
aladin.addCatalog(cat);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, target: "Abell 194", fov: 180, projection: 'AIT', showContextMenu: true});
|
||||
aladin.setImageSurvey('astron.nl/P/lotss_dr2_high')
|
||||
A.catalogFromSKAORucio("Abell 194", 90, {onClick: 'showTable'}, (cat) => {
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, target: "Abell 194", fov: 180, projection: 'SIN', showContextMenu: true});
|
||||
|
||||
A.catalogFromSKAORucio("m51", 90, {onClick: 'showTable'}, (cat) => {
|
||||
aladin.addCatalog(cat);
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
let aladin = A.aladin('#aladin-lite-div', {survey: "CDS/P/DSS2/color", target: 'Sgr a*', fov: 0.5, showContextMenu: true});
|
||||
// This table contains a s_region column containing stcs expressed regions
|
||||
// that are automatically parsed
|
||||
aladin.addCatalog(A.catalogFromURL('https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/data/alma-footprints.xml', {name: 'ALMA footprints', onClick: 'showTable', hoverColor: 'lightgreen'}));
|
||||
aladin.addCatalog(A.catalogFromURL('https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/data/alma-footprints.xml', {name: 'ALMA footprints', onClick: 'showTable'}));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<body>
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
|
||||
<div id='aladin-statsDiv'></div>
|
||||
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"homepage": "https://aladin.u-strasbg.fr/",
|
||||
"name": "aladin-lite",
|
||||
"type": "module",
|
||||
"version": "3.3.2",
|
||||
"version": "3.3.1-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser",
|
||||
"author": "Thomas Boch and Matthieu Baumann",
|
||||
"license": "GPL-3",
|
||||
@@ -33,7 +33,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"wasm": "wasm-pack build ./src/core --target web --release --out-name core -- --features webgl2 -Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort ",
|
||||
"predeploy": "npm run build && rm -rf aladin-lite*.tgz && npm pack",
|
||||
"predeploy": "npm run build && rm -rf aladin-lite.tgz && npm pack",
|
||||
"deploy": "python3 deploy/deploy.py",
|
||||
"build": "npm run wasm && vite build && cp examples/index.html dist/index.html",
|
||||
"dev": "npm run build && vite",
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "aladin-lite"
|
||||
description = "Aladin Lite v3 introduces a new graphical engine written in Rust with the use of WebGL"
|
||||
license = "BSD-3-Clause"
|
||||
repository = "https://github.com/cds-astro/aladin-lite"
|
||||
version = "3.3.2"
|
||||
version = "3.3.0"
|
||||
authors = [ "baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr",]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
@@ -43,9 +43,10 @@ pub struct HiPSProperties {
|
||||
// Associated with the HiPS
|
||||
url: String,
|
||||
max_order: u8,
|
||||
coo_frame: CooSystem,
|
||||
frame: CooSystem,
|
||||
tile_size: i32,
|
||||
formats: Vec<ImageExt>,
|
||||
dataproduct_subtype: Option<Vec<String>>,
|
||||
|
||||
is_planetary_body: Option<bool>,
|
||||
|
||||
@@ -102,7 +103,7 @@ impl HiPSProperties {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_frame(&self) -> CooSystem {
|
||||
self.coo_frame
|
||||
self.frame
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -124,6 +125,11 @@ impl HiPSProperties {
|
||||
pub fn get_initial_dec(&self) -> Option<f64> {
|
||||
self.hips_initial_dec
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_dataproduct_subtype(&self) -> &Option<Vec<String>> {
|
||||
&self.dataproduct_subtype
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
||||
@@ -60,14 +60,14 @@ pub struct Texture2D {
|
||||
pub enum SamplerType {
|
||||
Float,
|
||||
Integer,
|
||||
Unsigned,
|
||||
Unsigned
|
||||
}
|
||||
|
||||
use crate::image::format::ImageFormat;
|
||||
//use super::pixel::PixelType;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
impl Texture2D {
|
||||
pub fn create_from_path<P: AsRef<Path>, F: ImageFormat>(
|
||||
gl: &WebGlContext,
|
||||
@@ -145,6 +145,7 @@ impl Texture2D {
|
||||
onload.forget();
|
||||
onerror.forget();
|
||||
|
||||
|
||||
let gl = gl.clone();
|
||||
Ok(Texture2D {
|
||||
texture,
|
||||
@@ -162,12 +163,16 @@ impl Texture2D {
|
||||
tex_params: &'static [(u32, u32)],
|
||||
data: Option<&[<F::P as Pixel>::Item]>,
|
||||
) -> Result<Texture2D, JsValue> {
|
||||
let texture = Texture2D::create_empty_with_format::<F>(gl, width, height, tex_params)?;
|
||||
let texture = Texture2D::create_empty_with_format::<F>(
|
||||
gl,
|
||||
width,
|
||||
height,
|
||||
tex_params
|
||||
)?;
|
||||
|
||||
if let Some(data) = data {
|
||||
let buf_data = unsafe { F::view(data) };
|
||||
texture
|
||||
.bind()
|
||||
texture.bind()
|
||||
.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_array_buffer_view(
|
||||
0,
|
||||
0,
|
||||
@@ -230,6 +235,7 @@ impl Texture2D {
|
||||
None,
|
||||
)
|
||||
.expect("Texture 2D");
|
||||
//gl.generate_mipmap(WebGlRenderingCtx::TEXTURE_2D);
|
||||
|
||||
let gl = gl.clone();
|
||||
let metadata = Some(Rc::new(RefCell::new(Texture2DMeta {
|
||||
@@ -323,8 +329,7 @@ impl Texture2D {
|
||||
} else {
|
||||
// set the viewport as the FBO won't be the same dimension as the screen
|
||||
let metadata = self.metadata.as_ref().unwrap_abort().borrow();
|
||||
self.gl
|
||||
.viewport(x, y, metadata.width as i32, metadata.height as i32);
|
||||
self.gl.viewport(x, y, metadata.width as i32, metadata.height as i32);
|
||||
#[cfg(feature = "webgl2")]
|
||||
let value = match (metadata.format, metadata.type_) {
|
||||
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::UNSIGNED_BYTE) => {
|
||||
@@ -645,4 +650,4 @@ impl<'a> Texture2DBoundMut<'a> {
|
||||
)
|
||||
.expect("Sub texture 2d");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ use cgmath::{Vector2, Vector3};
|
||||
use futures::{io::BufReader, stream::StreamExt}; // for `next`
|
||||
|
||||
use crate::math::projection::*;
|
||||
pub const BLENDING_ANIM_DURATION: DeltaTime = DeltaTime::from_millis(200.0); // in ms
|
||||
pub const BLENDING_ANIM_DURATION: DeltaTime = DeltaTime::from_millis(400.0); // in ms
|
||||
//use crate::buffer::Tile;
|
||||
use crate::time::Time;
|
||||
use cgmath::InnerSpace;
|
||||
@@ -270,8 +270,6 @@ impl App {
|
||||
// Move the views of the different active surveys
|
||||
self.tile_fetcher.clear();
|
||||
// Loop over the surveys
|
||||
let raytracer = self.layers.get_raytracer();
|
||||
|
||||
for survey in self.layers.values_mut_hips() {
|
||||
if self.camera.get_texture_depth() == 0
|
||||
&& self
|
||||
@@ -292,8 +290,7 @@ impl App {
|
||||
let root_url = survey.get_config().get_root_url().to_string();
|
||||
let format = survey.get_config().get_format();
|
||||
|
||||
if let Some(tiles_iter) = survey.look_for_new_tiles(&mut self.camera, &self.projection)
|
||||
{
|
||||
if let Some(tiles_iter) = survey.look_for_new_tiles(&mut self.camera) {
|
||||
for tile_cell in tiles_iter.into_iter() {
|
||||
self.tile_fetcher.append(
|
||||
query::Tile::new(&tile_cell, creator_did.clone(), root_url.clone(), format),
|
||||
@@ -608,7 +605,7 @@ impl App {
|
||||
Resource::Tile(tile) => {
|
||||
if !has_camera_moved {
|
||||
if let Some(survey) =
|
||||
self.layers.get_mut_hips_from_cdid(&tile.get_hips_cdid())
|
||||
self.layers.get_mut_hips_from_url(&tile.get_hips_url())
|
||||
{
|
||||
let cfg = survey.get_config();
|
||||
|
||||
@@ -623,10 +620,10 @@ impl App {
|
||||
fov_coverage.intersects_cell(&neighbor_tile_cell)
|
||||
});
|
||||
|
||||
//let is_tile_root = tile.cell().depth() == delta_depth;
|
||||
//let _depth = tile.cell().depth();
|
||||
let is_tile_root = tile.cell().depth() == delta_depth;
|
||||
let _depth = tile.cell().depth();
|
||||
// do not perform tex_sub costly GPU calls while the camera is zooming
|
||||
if included_or_near_coverage {
|
||||
if is_tile_root || included_or_near_coverage {
|
||||
let is_missing = tile.missing();
|
||||
/*self.tile_fetcher.notify_tile(
|
||||
&tile,
|
||||
@@ -651,6 +648,7 @@ impl App {
|
||||
};
|
||||
|
||||
survey.add_tile(&cell, image, time_req)?;
|
||||
|
||||
self.request_redraw = true;
|
||||
|
||||
self.time_start_blending = Time::now();
|
||||
@@ -662,9 +660,9 @@ impl App {
|
||||
}
|
||||
}
|
||||
Resource::Allsky(allsky) => {
|
||||
let hips_cdid = allsky.get_hips_cdid();
|
||||
let hips_url = allsky.get_hips_url();
|
||||
|
||||
if let Some(survey) = self.layers.get_mut_hips_from_cdid(hips_cdid) {
|
||||
if let Some(survey) = self.layers.get_mut_hips_from_url(hips_url) {
|
||||
let is_missing = allsky.missing();
|
||||
if is_missing {
|
||||
// The allsky image is missing so we donwload all the tiles contained into
|
||||
@@ -693,8 +691,7 @@ impl App {
|
||||
}
|
||||
}
|
||||
Resource::PixelMetadata(metadata) => {
|
||||
if let Some(hips) = self.layers.get_mut_hips_from_cdid(&metadata.hips_cdid)
|
||||
{
|
||||
if let Some(hips) = self.layers.get_mut_hips_from_url(&metadata.hips_url) {
|
||||
let mut cfg = hips.get_config_mut();
|
||||
|
||||
if let Some(metadata) = *metadata.value.lock().unwrap_abort() {
|
||||
@@ -705,9 +702,9 @@ impl App {
|
||||
}
|
||||
}
|
||||
Resource::Moc(moc) => {
|
||||
let moc_hips_cdid = moc.get_hips_cdid();
|
||||
//let url = &moc_url[..moc_url.find("/Moc.fits").unwrap_abort()];
|
||||
if let Some(hips) = self.layers.get_mut_hips_from_cdid(moc_hips_cdid) {
|
||||
let moc_url = moc.get_url();
|
||||
let url = &moc_url[..moc_url.find("/Moc.fits").unwrap_abort()];
|
||||
if let Some(hips) = self.layers.get_mut_hips_from_url(url) {
|
||||
let request::moc::Moc { moc, .. } = moc;
|
||||
|
||||
if let Some(moc) = &*moc.lock().unwrap_abort() {
|
||||
@@ -759,13 +756,14 @@ impl App {
|
||||
// - there is at least one tile in its blending phase
|
||||
let blending_anim_occuring =
|
||||
(Time::now() - self.time_start_blending) < BLENDING_ANIM_DURATION;
|
||||
/*let start_fading = self.layers.values_hips().any(|hips| {
|
||||
|
||||
let start_fading = self.layers.values_hips().any(|hips| {
|
||||
if let Some(start_time) = hips.get_ready_time() {
|
||||
Time::now() - *start_time < BLENDING_ANIM_DURATION
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});*/
|
||||
});
|
||||
|
||||
// Finally update the camera that reset the flag camera changed
|
||||
//if has_camera_moved {
|
||||
@@ -789,7 +787,8 @@ impl App {
|
||||
})
|
||||
}
|
||||
|
||||
self.rendering = blending_anim_occuring | has_camera_moved | self.request_redraw /*| start_fading*/;
|
||||
self.rendering =
|
||||
blending_anim_occuring | has_camera_moved | self.request_redraw | start_fading;
|
||||
self.request_redraw = false;
|
||||
|
||||
self.draw(false)?;
|
||||
@@ -1190,13 +1189,17 @@ impl App {
|
||||
self.layers.get_layer_cfg(layer)
|
||||
}
|
||||
|
||||
pub(crate) fn set_hips_url(&mut self, cdid: &String, new_url: String) -> Result<(), JsValue> {
|
||||
self.layers.set_survey_url(cdid, new_url.clone())?;
|
||||
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_hips_from_url(&new_url).unwrap_abort();
|
||||
let hips = self.layers.get_hips_from_url(&new_url).unwrap_abort();
|
||||
// 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);
|
||||
self.tile_fetcher
|
||||
.launch_starting_hips_requests(hips, &mut self.downloader);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1299,8 +1302,12 @@ impl App {
|
||||
self.request_redraw = true;
|
||||
}
|
||||
|
||||
pub(crate) fn set_survey_url(&mut self, cdid: &String, new_url: String) -> Result<(), JsValue> {
|
||||
self.layers.set_survey_url(cdid, new_url)
|
||||
pub(crate) fn set_survey_url(
|
||||
&mut self,
|
||||
past_url: String,
|
||||
new_url: String,
|
||||
) -> Result<(), JsValue> {
|
||||
self.layers.set_survey_url(past_url, new_url)
|
||||
}
|
||||
|
||||
pub(crate) fn set_catalog_opacity(
|
||||
|
||||
@@ -10,7 +10,6 @@ use crate::HEALPixCoverage;
|
||||
use std::ops::Range;
|
||||
|
||||
use al_api::cell::HEALPixCellProjeted;
|
||||
use al_core::log::console_log;
|
||||
|
||||
pub fn project(
|
||||
cell: HEALPixCellProjeted,
|
||||
|
||||
@@ -9,7 +9,6 @@ pub enum UserAction {
|
||||
use super::{fov::FieldOfView, view_hpx_cells::ViewHpxCells};
|
||||
use crate::healpix::cell::HEALPixCell;
|
||||
use crate::healpix::coverage::HEALPixCoverage;
|
||||
use crate::math::angle::ToAngle;
|
||||
use crate::math::{projection::coo_space::XYZWModel, projection::domain::sdf::ProjDef};
|
||||
use al_core::{info, inforec, log};
|
||||
|
||||
@@ -211,31 +210,12 @@ impl CameraViewPort {
|
||||
|
||||
pub fn get_hpx_cells<'a>(
|
||||
&'a mut self,
|
||||
mut depth: u8,
|
||||
depth: u8,
|
||||
frame: CooSystem,
|
||||
) -> impl Iterator<Item = &'a HEALPixCell> {
|
||||
self.view_hpx_cells.get_cells(depth, frame)
|
||||
}
|
||||
|
||||
pub fn is_raytracing(&self, proj: &ProjectionType) -> bool {
|
||||
// Check whether the tile depth is 0 for square projection
|
||||
// definition domains i.e. Mercator
|
||||
if self.is_allsky() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check the projection
|
||||
match proj {
|
||||
ProjectionType::Tan(_) => self.aperture >= 100.0_f64.to_radians().to_angle(),
|
||||
ProjectionType::Mer(_) => self.aperture >= 200.0_f64.to_radians().to_angle(),
|
||||
ProjectionType::Stg(_) => self.aperture >= 200.0_f64.to_radians().to_angle(),
|
||||
ProjectionType::Sin(_) => false,
|
||||
ProjectionType::Ait(_) => false,
|
||||
ProjectionType::Mol(_) => false,
|
||||
ProjectionType::Zea(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn recompute_scissor(&self) {
|
||||
// Clear all the screen before updating the scissor
|
||||
//self.gl.scissor(0, 0, self.width as i32, self.height as i32);
|
||||
@@ -273,6 +253,41 @@ impl CameraViewPort {
|
||||
);
|
||||
}
|
||||
|
||||
fn set_canvas_size(&self, width: f32, height: f32) {
|
||||
let canvas = self
|
||||
.gl
|
||||
.canvas()
|
||||
.unwrap_abort()
|
||||
.dyn_into::<web_sys::HtmlCanvasElement>()
|
||||
.unwrap_abort();
|
||||
|
||||
canvas
|
||||
.style()
|
||||
.set_property("width", &format!("{}px", width))
|
||||
.unwrap_abort();
|
||||
canvas
|
||||
.style()
|
||||
.set_property("height", &format!("{}px", height))
|
||||
.unwrap_abort();
|
||||
/*grid_canvas
|
||||
.style()
|
||||
.set_property("width", &format!("{}px", width))
|
||||
.unwrap_abort();
|
||||
grid_canvas
|
||||
.style()
|
||||
.set_property("height", &format!("{}px", height))
|
||||
.unwrap_abort();*/
|
||||
|
||||
canvas.set_width(self.width as u32);
|
||||
canvas.set_height(self.height as u32);
|
||||
//grid_canvas.set_width(self.width as u32);
|
||||
//grid_canvas.set_height(self.height as u32);
|
||||
|
||||
// Once the canvas size is changed, we have to set the viewport as well
|
||||
self.gl
|
||||
.viewport(0, 0, self.width as i32, self.height as i32);
|
||||
}
|
||||
|
||||
pub fn set_screen_size(&mut self, width: f32, height: f32, projection: &ProjectionType) {
|
||||
self.width = (width as f32) * self.dpi;
|
||||
self.height = (height as f32) * self.dpi;
|
||||
@@ -295,18 +310,7 @@ impl CameraViewPort {
|
||||
));
|
||||
|
||||
// Update the size of the canvas
|
||||
let canvas = self
|
||||
.gl
|
||||
.canvas()
|
||||
.unwrap_abort()
|
||||
.dyn_into::<web_sys::HtmlCanvasElement>()
|
||||
.unwrap_abort();
|
||||
|
||||
canvas.set_width(self.width as u32);
|
||||
canvas.set_height(self.height as u32);
|
||||
// Once the canvas size is changed, we have to set the viewport as well
|
||||
self.gl
|
||||
.viewport(0, 0, self.width as i32, self.height as i32);
|
||||
self.set_canvas_size(width, height);
|
||||
// Once it is done, recompute the scissor
|
||||
self.recompute_scissor();
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ pub struct Downloader {
|
||||
requests: Vec<RequestType>,
|
||||
queried_list: HashSet<QueryId>,
|
||||
|
||||
cache: Cache<QueryId, Resource>,
|
||||
queried_cached_ids: Vec<QueryId>,
|
||||
cache: Cache<Url, Resource>,
|
||||
queried_cached_urls: Vec<Url>,
|
||||
}
|
||||
|
||||
use crate::fifo_cache::Cache;
|
||||
@@ -25,12 +25,12 @@ impl Downloader {
|
||||
let requests = Vec::with_capacity(32);
|
||||
let queried_list = HashSet::with_capacity(64);
|
||||
let cache = Cache::new();
|
||||
let queried_cached_ids = Vec::with_capacity(64);
|
||||
let queried_cached_urls = Vec::with_capacity(64);
|
||||
Self {
|
||||
requests,
|
||||
queried_list,
|
||||
cache,
|
||||
queried_cached_ids,
|
||||
queried_cached_urls,
|
||||
}
|
||||
}
|
||||
// Returns true if the fetch has been done
|
||||
@@ -39,8 +39,8 @@ impl Downloader {
|
||||
where
|
||||
T: Query,
|
||||
{
|
||||
let id = query.id();
|
||||
if self.cache.contains(id) {
|
||||
let url = query.url();
|
||||
if self.cache.contains(url) {
|
||||
//self.queried_cached_urls.push(url.clone());
|
||||
false
|
||||
} else {
|
||||
@@ -85,8 +85,8 @@ impl Downloader {
|
||||
self.queried_list.remove(&query_id);
|
||||
}
|
||||
|
||||
while let Some(id) = self.queried_cached_ids.pop() {
|
||||
if let Some(rsc) = self.cache.extract(&id) {
|
||||
while let Some(url) = self.queried_cached_urls.pop() {
|
||||
if let Some(rsc) = self.cache.extract(&url) {
|
||||
rscs.push(rsc);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ impl Downloader {
|
||||
}*/
|
||||
|
||||
pub fn delay_rsc(&mut self, rsc: Resource) {
|
||||
self.queried_cached_ids.push(rsc.id().clone());
|
||||
self.cache.insert(rsc.id().clone(), rsc);
|
||||
self.queried_cached_urls.push(rsc.url().clone());
|
||||
self.cache.insert(rsc.url().clone(), rsc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use super::request::RequestType;
|
||||
pub trait Query: Sized {
|
||||
type Request: From<Self> + Into<RequestType>;
|
||||
|
||||
fn hips_cdid(&self) -> &CreatorDid;
|
||||
fn url(&self) -> &Url;
|
||||
fn id(&self) -> &QueryId;
|
||||
}
|
||||
|
||||
@@ -17,18 +17,17 @@ pub struct Tile {
|
||||
pub cell: HEALPixCell,
|
||||
pub format: ImageFormatType,
|
||||
// The root url of the HiPS
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: Url,
|
||||
// The total url of the query
|
||||
pub url: Url,
|
||||
pub id: QueryId,
|
||||
}
|
||||
|
||||
use crate::renderable::CreatorDid;
|
||||
use crate::{healpix::cell::HEALPixCell, survey::config::HiPSConfig};
|
||||
impl Tile {
|
||||
pub fn new(
|
||||
cell: &HEALPixCell,
|
||||
hips_cdid: String,
|
||||
hips_id: String,
|
||||
hips_url: String,
|
||||
format: ImageFormatType,
|
||||
) -> Self {
|
||||
@@ -43,10 +42,10 @@ impl Tile {
|
||||
hips_url, depth, dir_idx, idx, ext
|
||||
);
|
||||
|
||||
let id = format!("{}{}{}{}", hips_cdid, depth, idx, ext);
|
||||
let id = format!("{}{}{}{}", hips_id, depth, idx, ext);
|
||||
|
||||
Tile {
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
url,
|
||||
cell: *cell,
|
||||
format,
|
||||
@@ -59,8 +58,8 @@ use super::request::tile::TileRequest;
|
||||
impl Query for Tile {
|
||||
type Request = TileRequest;
|
||||
|
||||
fn hips_cdid(&self) -> &CreatorDid {
|
||||
&self.hips_cdid
|
||||
fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
fn id(&self) -> &QueryId {
|
||||
@@ -74,7 +73,7 @@ pub struct Allsky {
|
||||
pub tile_size: i32,
|
||||
pub texture_size: i32,
|
||||
// The root url of the HiPS
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: Url,
|
||||
// The total url of the query
|
||||
pub url: Url,
|
||||
pub id: QueryId,
|
||||
@@ -82,20 +81,20 @@ pub struct Allsky {
|
||||
|
||||
impl Allsky {
|
||||
pub fn new(cfg: &HiPSConfig) -> Self {
|
||||
let hips_cdid = cfg.get_creator_did().to_string();
|
||||
let hips_url = cfg.get_root_url().to_string();
|
||||
let tile_size = cfg.get_tile_size();
|
||||
let texture_size = cfg.get_texture_size();
|
||||
let format = cfg.get_format();
|
||||
let ext = format.get_ext_file();
|
||||
|
||||
let url = format!("{}/Norder3/Allsky.{}", cfg.get_root_url(), ext);
|
||||
let url = format!("{}/Norder3/Allsky.{}", hips_url, ext);
|
||||
|
||||
let id = format!("{}Allsky{}", cfg.get_creator_did(), ext);
|
||||
|
||||
Allsky {
|
||||
tile_size,
|
||||
texture_size,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
url,
|
||||
format,
|
||||
id,
|
||||
@@ -107,8 +106,8 @@ use super::request::allsky::AllskyRequest;
|
||||
impl Query for Allsky {
|
||||
type Request = AllskyRequest;
|
||||
|
||||
fn hips_cdid(&self) -> &CreatorDid {
|
||||
&self.hips_cdid
|
||||
fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
fn id(&self) -> &QueryId {
|
||||
@@ -120,7 +119,7 @@ impl Query for Allsky {
|
||||
pub struct PixelMetadata {
|
||||
pub format: ImageFormatType,
|
||||
// The root url of the HiPS
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: Url,
|
||||
// The total url of the query
|
||||
pub url: Url,
|
||||
pub id: QueryId,
|
||||
@@ -128,15 +127,15 @@ pub struct PixelMetadata {
|
||||
|
||||
impl PixelMetadata {
|
||||
pub fn new(cfg: &HiPSConfig) -> Self {
|
||||
let hips_cdid = cfg.get_creator_did().to_string();
|
||||
let hips_url = cfg.get_root_url().to_string();
|
||||
let format = cfg.get_format();
|
||||
let ext = format.get_ext_file();
|
||||
|
||||
let url = format!("{}/Norder3/Allsky.{}", cfg.get_root_url(), ext);
|
||||
let url = format!("{}/Norder3/Allsky.{}", hips_url, ext);
|
||||
|
||||
let id = format!("{}Allsky{}", hips_cdid, ext);
|
||||
let id = format!("{}Allsky{}", cfg.get_creator_did(), ext);
|
||||
PixelMetadata {
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
url,
|
||||
format,
|
||||
id,
|
||||
@@ -148,8 +147,8 @@ use super::request::blank::PixelMetadataRequest;
|
||||
impl Query for PixelMetadata {
|
||||
type Request = PixelMetadataRequest;
|
||||
|
||||
fn hips_cdid(&self) -> &CreatorDid {
|
||||
&self.hips_cdid
|
||||
fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
fn id(&self) -> &QueryId {
|
||||
@@ -162,15 +161,10 @@ pub struct Moc {
|
||||
// The total url of the query
|
||||
pub url: Url,
|
||||
pub params: al_api::moc::MOC,
|
||||
pub hips_cdid: CreatorDid,
|
||||
}
|
||||
impl Moc {
|
||||
pub fn new(url: String, hips_cdid: CreatorDid, params: al_api::moc::MOC) -> Self {
|
||||
Moc {
|
||||
url,
|
||||
params,
|
||||
hips_cdid,
|
||||
}
|
||||
pub fn new(url: String, params: al_api::moc::MOC) -> Self {
|
||||
Moc { url, params }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,8 +172,8 @@ use super::request::moc::MOCRequest;
|
||||
impl Query for Moc {
|
||||
type Request = MOCRequest;
|
||||
|
||||
fn hips_cdid(&self) -> &CreatorDid {
|
||||
&self.hips_cdid
|
||||
fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
fn id(&self) -> &QueryId {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::downloader::query;
|
||||
use crate::renderable::CreatorDid;
|
||||
use al_core::image::format::ChannelType;
|
||||
use al_core::image::ImageType;
|
||||
|
||||
@@ -10,7 +9,7 @@ use fitsrs::{fits::Fits, hdu::data::InMemData};
|
||||
use super::{Request, RequestType};
|
||||
use crate::downloader::QueryId;
|
||||
pub struct AllskyRequest {
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: Url,
|
||||
pub url: Url,
|
||||
pub depth_tile: u8,
|
||||
pub id: QueryId,
|
||||
@@ -77,7 +76,7 @@ impl From<query::Allsky> for AllskyRequest {
|
||||
format,
|
||||
tile_size,
|
||||
url,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
texture_size,
|
||||
id,
|
||||
} = query;
|
||||
@@ -208,7 +207,7 @@ impl From<query::Allsky> for AllskyRequest {
|
||||
|
||||
Self {
|
||||
id,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
depth_tile,
|
||||
url,
|
||||
request,
|
||||
@@ -310,7 +309,7 @@ pub struct Allsky {
|
||||
pub time_req: Time,
|
||||
pub depth_tile: u8,
|
||||
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: Url,
|
||||
url: Url,
|
||||
}
|
||||
|
||||
@@ -321,8 +320,8 @@ impl Allsky {
|
||||
self.image.lock().unwrap_abort().is_none()
|
||||
}
|
||||
|
||||
pub fn get_hips_cdid(&self) -> &CreatorDid {
|
||||
&self.hips_cdid
|
||||
pub fn get_hips_url(&self) -> &Url {
|
||||
&self.hips_url
|
||||
}
|
||||
|
||||
pub fn get_url(&self) -> &Url {
|
||||
@@ -334,7 +333,7 @@ impl<'a> From<&'a AllskyRequest> for Option<Allsky> {
|
||||
fn from(request: &'a AllskyRequest) -> Self {
|
||||
let AllskyRequest {
|
||||
request,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
depth_tile,
|
||||
url,
|
||||
..
|
||||
@@ -347,7 +346,7 @@ impl<'a> From<&'a AllskyRequest> for Option<Allsky> {
|
||||
time_req: *time_request,
|
||||
// This is a clone on a Arc, it is supposed to be fast
|
||||
image: data.clone(),
|
||||
hips_cdid: hips_cdid.clone(),
|
||||
hips_url: hips_url.clone(),
|
||||
url: url.clone(),
|
||||
depth_tile: *depth_tile,
|
||||
})
|
||||
|
||||
@@ -2,7 +2,6 @@ use al_core::image::format::ChannelType;
|
||||
use std::io::Cursor;
|
||||
|
||||
use crate::downloader::query;
|
||||
use crate::renderable::CreatorDid;
|
||||
use fitsrs::fits::Fits;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -28,7 +27,7 @@ use crate::downloader::QueryId;
|
||||
pub struct PixelMetadataRequest {
|
||||
pub id: QueryId,
|
||||
pub url: Url,
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: Url,
|
||||
request: Request<Metadata>,
|
||||
}
|
||||
|
||||
@@ -50,7 +49,7 @@ impl From<query::PixelMetadata> for PixelMetadataRequest {
|
||||
let query::PixelMetadata {
|
||||
format,
|
||||
url,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
id,
|
||||
} = query;
|
||||
|
||||
@@ -127,7 +126,7 @@ impl From<query::PixelMetadata> for PixelMetadataRequest {
|
||||
Self {
|
||||
id,
|
||||
url,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
request,
|
||||
}
|
||||
}
|
||||
@@ -137,7 +136,7 @@ use std::sync::{Arc, Mutex};
|
||||
#[derive(Debug)]
|
||||
pub struct PixelMetadata {
|
||||
pub value: Arc<Mutex<Option<Metadata>>>,
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub hips_url: String,
|
||||
pub url: String,
|
||||
}
|
||||
use crate::Abort;
|
||||
@@ -145,7 +144,7 @@ impl<'a> From<&'a PixelMetadataRequest> for Option<PixelMetadata> {
|
||||
fn from(request: &'a PixelMetadataRequest) -> Self {
|
||||
let PixelMetadataRequest {
|
||||
request,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
url,
|
||||
..
|
||||
} = request;
|
||||
@@ -153,7 +152,7 @@ impl<'a> From<&'a PixelMetadataRequest> for Option<PixelMetadata> {
|
||||
let Request::<Metadata> { data, .. } = request;
|
||||
// It will always be resolved and found as we will request a well know tile (Norder0/Tile0)
|
||||
Some(PixelMetadata {
|
||||
hips_cdid: hips_cdid.clone(),
|
||||
hips_url: hips_url.clone(),
|
||||
url: url.to_string(),
|
||||
value: data.clone(),
|
||||
})
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::downloader::query;
|
||||
use crate::renderable::CreatorDid;
|
||||
|
||||
use super::{Request, RequestType};
|
||||
use crate::downloader::QueryId;
|
||||
@@ -9,7 +8,7 @@ use moclib::qty::Hpx;
|
||||
|
||||
pub struct MOCRequest {
|
||||
//pub id: QueryId,
|
||||
pub hips_cdid: CreatorDid,
|
||||
pub url: Url,
|
||||
pub params: al_api::moc::MOC,
|
||||
request: Request<HEALPixCoverage>,
|
||||
}
|
||||
@@ -49,11 +48,7 @@ use wasm_bindgen::JsValue;
|
||||
impl From<query::Moc> for MOCRequest {
|
||||
// Create a tile request associated to a HiPS
|
||||
fn from(query: query::Moc) -> Self {
|
||||
let query::Moc {
|
||||
url,
|
||||
params,
|
||||
hips_cdid,
|
||||
} = query;
|
||||
let query::Moc { url, params } = query;
|
||||
|
||||
let url_clone = url.clone();
|
||||
|
||||
@@ -93,8 +88,7 @@ impl From<query::Moc> for MOCRequest {
|
||||
|
||||
Self {
|
||||
//id,
|
||||
//url,
|
||||
hips_cdid,
|
||||
url,
|
||||
request,
|
||||
params,
|
||||
}
|
||||
@@ -105,12 +99,12 @@ use std::sync::{Arc, Mutex};
|
||||
pub struct Moc {
|
||||
pub moc: Arc<Mutex<Option<HEALPixCoverage>>>,
|
||||
pub params: al_api::moc::MOC,
|
||||
pub hips_cdid: Url,
|
||||
pub url: Url,
|
||||
}
|
||||
|
||||
impl Moc {
|
||||
pub fn get_hips_cdid(&self) -> &Url {
|
||||
&self.hips_cdid
|
||||
pub fn get_url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +112,7 @@ impl<'a> From<&'a MOCRequest> for Option<Moc> {
|
||||
fn from(request: &'a MOCRequest) -> Self {
|
||||
let MOCRequest {
|
||||
request,
|
||||
hips_cdid,
|
||||
url,
|
||||
params,
|
||||
..
|
||||
} = request;
|
||||
@@ -127,7 +121,7 @@ impl<'a> From<&'a MOCRequest> for Option<Moc> {
|
||||
Some(Moc {
|
||||
// This is a clone on a Arc, it is supposed to be fast
|
||||
moc: data.clone(),
|
||||
hips_cdid: hips_cdid.clone(),
|
||||
url: url.clone(),
|
||||
params: params.clone(),
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -95,7 +95,7 @@ impl RequestType {
|
||||
RequestType::Tile(request) => &request.id,
|
||||
RequestType::Allsky(request) => &request.id,
|
||||
RequestType::PixelMetadata(request) => &request.id,
|
||||
RequestType::Moc(request) => &request.hips_cdid,
|
||||
RequestType::Moc(request) => &request.url,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,12 +125,12 @@ pub enum Resource {
|
||||
}
|
||||
|
||||
impl Resource {
|
||||
pub fn id(&self) -> &String {
|
||||
pub fn url(&self) -> &Url {
|
||||
match self {
|
||||
Resource::Tile(tile) => tile.get_hips_cdid(),
|
||||
Resource::Allsky(allsky) => allsky.get_hips_cdid(),
|
||||
Resource::PixelMetadata(PixelMetadata { hips_cdid, .. }) => hips_cdid,
|
||||
Resource::Moc(moc) => moc.get_hips_cdid(),
|
||||
Resource::Tile(tile) => tile.get_url(),
|
||||
Resource::Allsky(allsky) => allsky.get_url(),
|
||||
Resource::PixelMetadata(PixelMetadata { url, .. }) => url,
|
||||
Resource::Moc(moc) => moc.get_url(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::healpix::cell::HEALPixCell;
|
||||
use crate::renderable::CreatorDid;
|
||||
use al_core::image::format::{ChannelType, ImageFormatType, RGB8U, RGBA8U};
|
||||
|
||||
use crate::downloader::query;
|
||||
@@ -13,7 +12,7 @@ pub struct TileRequest {
|
||||
pub id: QueryId,
|
||||
|
||||
cell: HEALPixCell,
|
||||
hips_cdid: CreatorDid,
|
||||
hips_url: Url,
|
||||
url: Url,
|
||||
format: ImageFormatType,
|
||||
|
||||
@@ -58,7 +57,7 @@ impl From<query::Tile> for TileRequest {
|
||||
format,
|
||||
cell,
|
||||
url,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
id,
|
||||
} = query;
|
||||
|
||||
@@ -178,7 +177,7 @@ impl From<query::Tile> for TileRequest {
|
||||
cell,
|
||||
format,
|
||||
id,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
url,
|
||||
request,
|
||||
}
|
||||
@@ -192,7 +191,7 @@ pub struct Tile {
|
||||
pub time_req: Time,
|
||||
pub cell: HEALPixCell,
|
||||
pub format: ImageFormatType,
|
||||
hips_cdid: CreatorDid,
|
||||
hips_url: Url,
|
||||
url: Url,
|
||||
}
|
||||
|
||||
@@ -204,8 +203,8 @@ impl Tile {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_hips_cdid(&self) -> &CreatorDid {
|
||||
&self.hips_cdid
|
||||
pub fn get_hips_url(&self) -> &Url {
|
||||
&self.hips_url
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -229,7 +228,7 @@ impl<'a> From<&'a TileRequest> for Option<Tile> {
|
||||
let TileRequest {
|
||||
cell,
|
||||
request,
|
||||
hips_cdid,
|
||||
hips_url,
|
||||
url,
|
||||
format,
|
||||
..
|
||||
@@ -243,7 +242,7 @@ impl<'a> From<&'a TileRequest> for Option<Tile> {
|
||||
time_req: *time_request,
|
||||
// This is a clone on a Arc, it is supposed to be fast
|
||||
image: data.clone(),
|
||||
hips_cdid: hips_cdid.clone(),
|
||||
hips_url: hips_url.clone(),
|
||||
url: url.clone(),
|
||||
format: *format,
|
||||
})
|
||||
|
||||
@@ -404,8 +404,8 @@ impl WebClient {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = setHiPSUrl)]
|
||||
pub fn set_hips_url(&mut self, cdid: String, new_url: String) -> Result<(), JsValue> {
|
||||
self.app.set_hips_url(&cdid, new_url)
|
||||
pub fn set_hips_url(&mut self, past_url: String, new_url: String) -> Result<(), JsValue> {
|
||||
self.app.set_hips_url(past_url, new_url)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = getImageMetadata)]
|
||||
@@ -422,8 +422,8 @@ impl WebClient {
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = setImageSurveyUrl)]
|
||||
pub fn set_survey_url(&mut self, cdid: String, new_url: String) -> Result<(), JsValue> {
|
||||
self.app.set_survey_url(&cdid, new_url)
|
||||
pub fn set_survey_url(&mut self, past_url: String, new_url: String) -> Result<(), JsValue> {
|
||||
self.app.set_survey_url(past_url, new_url)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = setBackgroundColor)]
|
||||
|
||||
@@ -4,10 +4,10 @@ pub mod uv;
|
||||
|
||||
use al_api::hips::ImageExt;
|
||||
use al_api::hips::ImageMetadata;
|
||||
|
||||
use al_core::colormap::Colormap;
|
||||
use al_core::colormap::Colormaps;
|
||||
use al_core::image::format::ChannelType;
|
||||
use al_core::image::format::ImageFormatType;
|
||||
use al_core::image::Image;
|
||||
use al_core::log::console_log;
|
||||
use al_core::shader::Shader;
|
||||
@@ -30,7 +30,6 @@ use crate::math::angle::ToAngle;
|
||||
use crate::math::lonlat::LonLat;
|
||||
use crate::time::Time;
|
||||
use al_core::log;
|
||||
use std::collections::HashSet;
|
||||
|
||||
// Recursively compute the number of subdivision needed for a cell
|
||||
// to not be too much skewed
|
||||
@@ -283,7 +282,9 @@ pub fn get_raster_shader<'a>(
|
||||
shaders: &'a mut ShaderManager,
|
||||
config: &HiPSConfig,
|
||||
) -> Result<&'a Shader, JsValue> {
|
||||
if config.get_format().is_colored() && cmap.label() == "native" {
|
||||
let colored_hips = config.is_colored();
|
||||
|
||||
if colored_hips && cmap.label() == "native" {
|
||||
crate::shader::get_shader(gl, shaders, "RasterizerVS", "RasterizerColorFS")
|
||||
} else {
|
||||
if config.tex_storing_unsigned_int {
|
||||
@@ -317,8 +318,8 @@ pub fn get_raytracer_shader<'a>(
|
||||
shaders: &'a mut ShaderManager,
|
||||
config: &HiPSConfig,
|
||||
) -> Result<&'a Shader, JsValue> {
|
||||
//let colored_hips = config.is_colored();
|
||||
if config.get_format().is_colored() && cmap.label() == "native" {
|
||||
let colored_hips = config.is_colored();
|
||||
if colored_hips && cmap.label() == "native" {
|
||||
crate::shader::get_shader(gl, shaders, "RayTracerVS", "RayTracerColorFS")
|
||||
} else {
|
||||
if config.tex_storing_unsigned_int {
|
||||
@@ -529,13 +530,11 @@ impl HiPS {
|
||||
pub fn look_for_new_tiles<'a>(
|
||||
&'a mut self,
|
||||
camera: &'a mut CameraViewPort,
|
||||
proj: &ProjectionType,
|
||||
) -> Option<impl Iterator<Item = HEALPixCell> + 'a> {
|
||||
) -> Option<impl Iterator<Item = &'a HEALPixCell> + 'a> {
|
||||
// do not add tiles if the view is already at depth 0
|
||||
let mut depth_tile = (camera.get_texture_depth() + self.get_config().delta_depth())
|
||||
let depth_tile = (camera.get_texture_depth() + self.get_config().delta_depth())
|
||||
.min(self.get_config().get_max_depth_tile())
|
||||
.max(self.get_config().get_min_depth_tile());
|
||||
let dd = self.get_config().delta_depth();
|
||||
|
||||
//let min_depth_tile = self.get_min_depth_tile();
|
||||
//let delta_depth = self.get_config().delta_depth();
|
||||
@@ -550,31 +549,13 @@ impl HiPS {
|
||||
//if depth_tile >= min_bound_depth {
|
||||
//let depth_tile = depth_tile.max(min_bound_depth);
|
||||
let survey_frame = self.get_config().get_frame();
|
||||
let mut already_considered_tiles = HashSet::new();
|
||||
|
||||
// raytracer is rendering and the shader only renders HPX texture cells of depth 0
|
||||
if camera.is_raytracing(proj) {
|
||||
depth_tile = 0;
|
||||
}
|
||||
|
||||
let tile_cells_iter = camera
|
||||
.get_hpx_cells(depth_tile, survey_frame)
|
||||
//.flat_map(move |cell| {
|
||||
// let texture_cell = cell.get_texture_cell(delta_depth);
|
||||
// texture_cell.get_tile_cells(delta_depth)
|
||||
//})
|
||||
.flat_map(move |tile_cell| {
|
||||
let tex_cell = tile_cell.get_texture_cell(dd);
|
||||
//console_log(&format!("{:?}, dd:{:?}", tex_cell, dd));
|
||||
tex_cell.get_tile_cells(dd)
|
||||
})
|
||||
.filter(move |tile_cell| {
|
||||
if already_considered_tiles.contains(tile_cell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
already_considered_tiles.insert(*tile_cell);
|
||||
|
||||
if let Some(moc) = self.footprint_moc.as_ref() {
|
||||
moc.intersects_cell(tile_cell) && !self.update_priority_tile(tile_cell)
|
||||
} else {
|
||||
@@ -608,8 +589,13 @@ impl HiPS {
|
||||
self.textures.contains_tile(cell)
|
||||
}
|
||||
|
||||
pub fn update(&mut self, camera: &mut CameraViewPort, projection: &ProjectionType) {
|
||||
let raytracing = camera.is_raytracing(projection);
|
||||
pub fn update(
|
||||
&mut self,
|
||||
raytracer: &RayTracer,
|
||||
camera: &mut CameraViewPort,
|
||||
projection: &ProjectionType,
|
||||
) {
|
||||
let raytracing = raytracer.is_rendering(camera);
|
||||
|
||||
let vertices_recomputation_needed =
|
||||
!raytracing && (self.textures.reset_available_tiles() | camera.has_moved());
|
||||
@@ -632,7 +618,7 @@ impl HiPS {
|
||||
self.textures.set_format(&self.gl, ext)
|
||||
}
|
||||
|
||||
/*pub fn get_fading_factor(&self) -> f32 {
|
||||
pub fn get_fading_factor(&self) -> f32 {
|
||||
self.textures
|
||||
.start_time
|
||||
.map(|start_time| {
|
||||
@@ -640,7 +626,7 @@ impl HiPS {
|
||||
fading.clamp(0.0, 1.0)
|
||||
})
|
||||
.unwrap_or(0.0)
|
||||
}*/
|
||||
}
|
||||
|
||||
pub fn is_allsky(&self) -> bool {
|
||||
self.textures.config().is_allsky
|
||||
@@ -732,22 +718,15 @@ impl HiPS {
|
||||
|
||||
if let Some(cell) = cell {
|
||||
let texture_to_draw = if self.textures.contains(cell) {
|
||||
let parent_cell = self.textures.get_nearest_parent(cell);
|
||||
|
||||
if let Some(ending_cell_in_tex) = self.textures.get(cell) {
|
||||
if let Some(parent_cell) = self.textures.get_nearest_parent(cell) {
|
||||
if let Some(starting_cell_in_tex) = self.textures.get(&parent_cell) {
|
||||
Some(TextureToDraw::new(
|
||||
starting_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
} else {
|
||||
// no blending here
|
||||
Some(TextureToDraw::new(
|
||||
ending_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
}
|
||||
if let Some(starting_cell_in_tex) = self.textures.get(&parent_cell) {
|
||||
Some(TextureToDraw::new(
|
||||
starting_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
} else {
|
||||
Some(TextureToDraw::new(
|
||||
ending_cell_in_tex,
|
||||
@@ -759,36 +738,22 @@ impl HiPS {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
if let Some(parent_cell) = self.textures.get_nearest_parent(cell) {
|
||||
if let Some(ending_cell_in_tex) = self.textures.get(&parent_cell) {
|
||||
if let Some(grand_parent_cell) =
|
||||
self.textures.get_nearest_parent(&parent_cell)
|
||||
{
|
||||
if let Some(starting_cell_in_tex) =
|
||||
self.textures.get(&grand_parent_cell)
|
||||
{
|
||||
Some(TextureToDraw::new(
|
||||
starting_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
} else {
|
||||
// no blending
|
||||
Some(TextureToDraw::new(
|
||||
ending_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Some(TextureToDraw::new(
|
||||
ending_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
}
|
||||
let parent_cell = self.textures.get_nearest_parent(cell);
|
||||
let grand_parent_cell = self.textures.get_nearest_parent(&parent_cell);
|
||||
|
||||
if let Some(ending_cell_in_tex) = self.textures.get(&parent_cell) {
|
||||
if let Some(starting_cell_in_tex) = self.textures.get(&grand_parent_cell) {
|
||||
Some(TextureToDraw::new(
|
||||
starting_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
Some(TextureToDraw::new(
|
||||
ending_cell_in_tex,
|
||||
ending_cell_in_tex,
|
||||
cell,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@@ -1013,7 +978,6 @@ impl HiPS {
|
||||
camera: &CameraViewPort,
|
||||
raytracer: &RayTracer,
|
||||
cfg: &ImageMetadata,
|
||||
proj: &ProjectionType,
|
||||
) -> Result<(), JsValue> {
|
||||
// Get the coo system transformation matrix
|
||||
let selected_frame = camera.get_coo_system();
|
||||
@@ -1025,7 +989,7 @@ impl HiPS {
|
||||
let w2v = c * (*camera.get_w2m());
|
||||
let v2w = w2v.transpose();
|
||||
|
||||
let raytracing = camera.is_raytracing(proj);
|
||||
let raytracing = raytracer.is_rendering(camera);
|
||||
let config = self.get_config();
|
||||
|
||||
self.gl.enable(WebGl2RenderingContext::BLEND);
|
||||
@@ -1038,8 +1002,8 @@ impl HiPS {
|
||||
} = cfg;
|
||||
|
||||
// Add starting fading
|
||||
//let fading = self.get_fading_factor();
|
||||
//let opacity = opacity * fading;
|
||||
let fading = self.get_fading_factor();
|
||||
let opacity = opacity * fading;
|
||||
// Get the colormap from the color
|
||||
let cmap = colormaps.get(color.cmap_name.as_ref());
|
||||
|
||||
@@ -1057,7 +1021,7 @@ impl HiPS {
|
||||
.attach_uniform("model", &w2v)
|
||||
.attach_uniform("inv_model", &v2w)
|
||||
.attach_uniform("current_time", &utils::get_current_time())
|
||||
.attach_uniform("opacity", opacity)
|
||||
.attach_uniform("opacity", &opacity)
|
||||
.attach_uniforms_from(colormaps);
|
||||
|
||||
raytracer.draw(&shader);
|
||||
@@ -1085,7 +1049,7 @@ impl HiPS {
|
||||
.attach_uniform("model", &w2v)
|
||||
.attach_uniform("inv_model", &v2w)
|
||||
.attach_uniform("current_time", &utils::get_current_time())
|
||||
.attach_uniform("opacity", opacity)
|
||||
.attach_uniform("opacity", &opacity)
|
||||
.attach_uniforms_from(colormaps)
|
||||
.bind_vertex_array_object_ref(&self.vao)
|
||||
.draw_elements_with_i32(
|
||||
|
||||
@@ -239,4 +239,11 @@ impl RayTracer {
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_rendering(&self, camera: &CameraViewPort) -> bool {
|
||||
// Check whether the tile depth is 0 for square projection
|
||||
// definition domains i.e. Mercator
|
||||
let depth = camera.get_texture_depth();
|
||||
camera.is_allsky() || depth == 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,17 +47,15 @@ pub trait Renderer {
|
||||
}
|
||||
|
||||
pub(crate) type Url = String;
|
||||
pub(crate) type CreatorDid = String;
|
||||
|
||||
type LayerId = String;
|
||||
pub struct Layers {
|
||||
// Surveys to query
|
||||
surveys: HashMap<CreatorDid, HiPS>,
|
||||
surveys: HashMap<Url, HiPS>,
|
||||
images: HashMap<Url, Image>,
|
||||
// The meta data associated with a layer
|
||||
meta: HashMap<LayerId, ImageMetadata>,
|
||||
// Hashmap between FITS image urls/HiPS creatorDid and layers
|
||||
ids: HashMap<LayerId, String>,
|
||||
// Hashmap between urls and layers
|
||||
urls: HashMap<LayerId, Url>,
|
||||
// Layers given in a specific order to draw
|
||||
layers: Vec<LayerId>,
|
||||
|
||||
@@ -114,7 +112,7 @@ impl Layers {
|
||||
let surveys = HashMap::new();
|
||||
let images = HashMap::new();
|
||||
let meta = HashMap::new();
|
||||
let ids = HashMap::new();
|
||||
let urls = HashMap::new();
|
||||
let layers = Vec::new();
|
||||
|
||||
// - The raytracer is a mesh covering the view. Each pixel of this mesh
|
||||
@@ -166,7 +164,7 @@ impl Layers {
|
||||
images,
|
||||
|
||||
meta,
|
||||
ids,
|
||||
urls,
|
||||
layers,
|
||||
|
||||
raytracer,
|
||||
@@ -178,19 +176,19 @@ impl Layers {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_survey_url(&mut self, cdid: &CreatorDid, new_url: String) -> Result<(), JsValue> {
|
||||
if let Some(mut survey) = self.surveys.get_mut(cdid) {
|
||||
pub fn set_survey_url(&mut self, past_url: String, new_url: String) -> Result<(), JsValue> {
|
||||
if let Some(mut survey) = self.surveys.remove(&past_url) {
|
||||
// update the root_url
|
||||
survey.get_config_mut().set_root_url(new_url.clone());
|
||||
|
||||
//self.surveys.insert(new_url.clone(), survey);
|
||||
self.surveys.insert(new_url.clone(), survey);
|
||||
|
||||
// update all the layer urls
|
||||
/*for id in self.ids.values_mut() {
|
||||
if *id == past_url {
|
||||
*id = new_url.clone();
|
||||
for url in self.urls.values_mut() {
|
||||
if *url == past_url {
|
||||
*url = new_url.clone();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -214,10 +212,6 @@ impl Layers {
|
||||
self.background_color = color;
|
||||
}
|
||||
|
||||
pub fn get_raytracer(&self) -> &RayTracer {
|
||||
&self.raytracer
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
camera: &mut CameraViewPort,
|
||||
@@ -226,15 +220,15 @@ impl Layers {
|
||||
projection: &ProjectionType,
|
||||
) -> Result<(), JsValue> {
|
||||
let raytracer = &self.raytracer;
|
||||
let raytracing = camera.is_raytracing(projection);
|
||||
let raytracing = raytracer.is_rendering(camera);
|
||||
|
||||
// Check whether a survey to plot is allsky
|
||||
// if neither are, we draw a font
|
||||
// if there are, we do not draw nothing
|
||||
let render_background_color = !self.layers.iter().any(|layer| {
|
||||
let meta = self.meta.get(layer).unwrap_abort();
|
||||
let cdid = self.ids.get(layer).unwrap_abort();
|
||||
if let Some(survey) = self.surveys.get(cdid) {
|
||||
let url = self.urls.get(layer).unwrap_abort();
|
||||
if let Some(survey) = self.surveys.get(url) {
|
||||
let hips_cfg = survey.get_config();
|
||||
(survey.is_allsky() || hips_cfg.get_format().get_channel() == ChannelType::RGB8U)
|
||||
&& meta.opacity == 1.0
|
||||
@@ -276,8 +270,8 @@ impl Layers {
|
||||
for (idx_layer, layer) in self.layers.iter().enumerate().skip(1) {
|
||||
let meta = self.meta.get(layer).expect("Meta should be found");
|
||||
|
||||
let id = self.ids.get(layer).expect("Url should be found");
|
||||
if let Some(survey) = self.surveys.get_mut(id) {
|
||||
let url = self.urls.get(layer).expect("Url should be found");
|
||||
if let Some(survey) = self.surveys.get_mut(url) {
|
||||
let hips_cfg = survey.get_config();
|
||||
|
||||
let fully_covering_survey = (survey.is_allsky()
|
||||
@@ -294,13 +288,13 @@ impl Layers {
|
||||
let draw_opt = self.meta.get(layer).expect("Meta should be found");
|
||||
if draw_opt.visible() {
|
||||
// 1. Update the survey if necessary
|
||||
let id = self.ids.get(layer).expect("Url should be found");
|
||||
if let Some(survey) = self.surveys.get_mut(id) {
|
||||
survey.update(camera, projection);
|
||||
let url = self.urls.get(layer).expect("Url should be found");
|
||||
if let Some(survey) = self.surveys.get_mut(url) {
|
||||
survey.update(&self.raytracer, camera, projection);
|
||||
|
||||
// 2. Draw it if its opacity is not null
|
||||
survey.draw(shaders, colormaps, camera, raytracer, draw_opt, projection)?;
|
||||
} else if let Some(image) = self.images.get_mut(id) {
|
||||
survey.draw(shaders, colormaps, camera, raytracer, draw_opt)?;
|
||||
} else if let Some(image) = self.images.get_mut(url) {
|
||||
image.update(camera, projection)?;
|
||||
|
||||
// 2. Draw it if its opacity is not null
|
||||
@@ -332,7 +326,7 @@ impl Layers {
|
||||
));
|
||||
// Color configs, and urls are indexed by layer
|
||||
self.meta.remove(layer).ok_or(err_layer_not_found.clone())?;
|
||||
let id = self.ids.remove(layer).ok_or(err_layer_not_found.clone())?;
|
||||
let url = self.urls.remove(layer).ok_or(err_layer_not_found.clone())?;
|
||||
// layer from layers does also need to be removed
|
||||
let id_layer = self
|
||||
.layers
|
||||
@@ -348,26 +342,26 @@ impl Layers {
|
||||
camera.set_longitude_reversed(longitude_reversed, proj);
|
||||
|
||||
// Check if the url is still used
|
||||
let id_still_used = self.ids.values().any(|rem_id| rem_id == &id);
|
||||
if id_still_used {
|
||||
let url_still_used = self.urls.values().any(|rem_url| rem_url == &url);
|
||||
if url_still_used {
|
||||
// Keep the resource whether it is a HiPS or a FITS
|
||||
Ok(id_layer)
|
||||
} else {
|
||||
// Resource not needed anymore
|
||||
if let Some(s) = self.surveys.remove(&id) {
|
||||
if let Some(s) = self.surveys.remove(&url) {
|
||||
// A HiPS has been found and removed
|
||||
let hips_frame = s.get_config().get_frame();
|
||||
// remove the frame
|
||||
camera.unregister_view_frame(hips_frame, proj);
|
||||
|
||||
Ok(id_layer)
|
||||
} else if let Some(_) = self.images.remove(&id) {
|
||||
} else if let Some(_) = self.images.remove(&url) {
|
||||
// A FITS image has been found and removed
|
||||
Ok(id_layer)
|
||||
} else {
|
||||
Err(JsValue::from_str(&format!(
|
||||
"Url found {:?} is associated to no surveys.",
|
||||
id
|
||||
url
|
||||
)))
|
||||
}
|
||||
}
|
||||
@@ -389,11 +383,11 @@ impl Layers {
|
||||
self.layers[id_layer] = new_layer.to_string();
|
||||
|
||||
let meta = self.meta.remove(layer).ok_or(err_layer_not_found.clone())?;
|
||||
let id = self.ids.remove(layer).ok_or(err_layer_not_found)?;
|
||||
let url = self.urls.remove(layer).ok_or(err_layer_not_found)?;
|
||||
|
||||
// Add the new
|
||||
self.meta.insert(new_layer.to_string(), meta);
|
||||
self.ids.insert(new_layer.to_string(), id);
|
||||
self.urls.insert(new_layer.to_string(), url);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -457,16 +451,13 @@ impl Layers {
|
||||
camera.set_longitude_reversed(longitude_reversed, proj);
|
||||
|
||||
// 3. Add the image survey
|
||||
let creator_did = String::from(properties.get_creator_did());
|
||||
let url = String::from(properties.get_url());
|
||||
// The layer does not already exist
|
||||
// Let's check if no other hipses points to the
|
||||
// same url than `hips`
|
||||
let cdid_already_found = self
|
||||
.surveys
|
||||
.keys()
|
||||
.any(|hips_cdid| hips_cdid == &creator_did);
|
||||
let url_already_found = self.surveys.keys().any(|hips_url| hips_url == &url);
|
||||
|
||||
if !cdid_already_found {
|
||||
if !url_already_found {
|
||||
// The url is not processed yet
|
||||
let cfg = HiPSConfig::new(&properties, img_ext)?;
|
||||
|
||||
@@ -484,14 +475,14 @@ impl Layers {
|
||||
let hips = HiPS::new(cfg, gl, camera)?;
|
||||
// add the frame to the camera
|
||||
|
||||
self.surveys.insert(creator_did.clone(), hips);
|
||||
self.surveys.insert(url.clone(), hips);
|
||||
}
|
||||
|
||||
self.ids.insert(layer.clone(), creator_did.clone());
|
||||
self.urls.insert(layer.clone(), url.clone());
|
||||
|
||||
let hips = self
|
||||
.surveys
|
||||
.get(&creator_did)
|
||||
.get(&url)
|
||||
.ok_or(JsValue::from_str("HiPS not found"))?;
|
||||
Ok(hips)
|
||||
}
|
||||
@@ -550,7 +541,7 @@ impl Layers {
|
||||
self.images.insert(url.clone(), image);
|
||||
}
|
||||
|
||||
self.ids.insert(layer.clone(), url.clone());
|
||||
self.urls.insert(layer.clone(), url.clone());
|
||||
|
||||
let fits = self
|
||||
.images
|
||||
@@ -626,26 +617,26 @@ impl Layers {
|
||||
// Accessors
|
||||
// HiPSes getters
|
||||
pub fn get_hips_from_layer(&self, layer: &str) -> Option<&HiPS> {
|
||||
self.ids
|
||||
self.urls
|
||||
.get(layer)
|
||||
.map(|cdid| self.surveys.get(cdid))
|
||||
.map(|url| self.surveys.get(url))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn get_mut_hips_from_layer(&mut self, layer: &str) -> Option<&mut HiPS> {
|
||||
if let Some(cdid) = self.ids.get_mut(layer) {
|
||||
self.surveys.get_mut(cdid)
|
||||
if let Some(url) = self.urls.get_mut(layer) {
|
||||
self.surveys.get_mut(url)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut_hips_from_cdid(&mut self, cdid: &str) -> Option<&mut HiPS> {
|
||||
self.surveys.get_mut(cdid)
|
||||
pub fn get_mut_hips_from_url(&mut self, root_url: &str) -> Option<&mut HiPS> {
|
||||
self.surveys.get_mut(root_url)
|
||||
}
|
||||
|
||||
pub fn get_hips_from_cdid(&mut self, cdid: &str) -> Option<&HiPS> {
|
||||
self.surveys.get(cdid)
|
||||
pub fn get_hips_from_url(&mut self, root_url: &str) -> Option<&HiPS> {
|
||||
self.surveys.get(root_url)
|
||||
}
|
||||
|
||||
pub fn values_hips(&self) -> impl Iterator<Item = &HiPS> {
|
||||
@@ -658,7 +649,7 @@ impl Layers {
|
||||
|
||||
// Fits images getters
|
||||
pub fn get_mut_image_from_layer(&mut self, layer: &str) -> Option<&mut Image> {
|
||||
if let Some(url) = self.ids.get(layer) {
|
||||
if let Some(url) = self.urls.get(layer) {
|
||||
self.images.get_mut(url)
|
||||
} else {
|
||||
None
|
||||
@@ -666,7 +657,7 @@ impl Layers {
|
||||
}
|
||||
|
||||
pub fn get_image_from_layer(&self, layer: &str) -> Option<&Image> {
|
||||
self.ids
|
||||
self.urls
|
||||
.get(layer)
|
||||
.map(|url| self.images.get(url))
|
||||
.flatten()
|
||||
|
||||
@@ -134,11 +134,11 @@ pub struct ImageSurveyTextures {
|
||||
size: usize,
|
||||
|
||||
pub textures: HashMap<HEALPixCell, Texture>,
|
||||
//pub base_textures: [Texture; NUM_HPX_TILES_DEPTH_ZERO],
|
||||
pub base_textures: [Texture; NUM_HPX_TILES_DEPTH_ZERO],
|
||||
//pub cutoff_values_tile: Rc<RefCell<HashMap<HEALPixCell, (f32, f32)>>>,
|
||||
|
||||
// Array of 2D textures
|
||||
texture_2d_array: Texture2DArray,
|
||||
texture_2d_array: Rc<Texture2DArray>,
|
||||
|
||||
// A boolean ensuring the root textures
|
||||
// have already been loaded
|
||||
@@ -146,7 +146,6 @@ pub struct ImageSurveyTextures {
|
||||
pub start_time: Option<Time>,
|
||||
|
||||
available_tiles_during_frame: bool,
|
||||
//num_base_textures: usize,
|
||||
//exec: Rc<RefCell<TaskExecutor>>,
|
||||
}
|
||||
|
||||
@@ -177,11 +176,11 @@ impl ImageSurveyTextures {
|
||||
// Ensures there is at least space for the 12
|
||||
// root textures
|
||||
debug_assert!(size >= NUM_HPX_TILES_DEPTH_ZERO);
|
||||
let heap = HEALPixCellHeap::with_capacity(size);
|
||||
let heap = HEALPixCellHeap::with_capacity(size - NUM_HPX_TILES_DEPTH_ZERO);
|
||||
let textures = HashMap::with_capacity(size);
|
||||
|
||||
let now = Time::now();
|
||||
/*let base_textures = [
|
||||
let base_textures = [
|
||||
Texture::new(&HEALPixCell(0, 0), 0, now),
|
||||
Texture::new(&HEALPixCell(0, 1), 1, now),
|
||||
Texture::new(&HEALPixCell(0, 2), 2, now),
|
||||
@@ -194,31 +193,34 @@ impl ImageSurveyTextures {
|
||||
Texture::new(&HEALPixCell(0, 9), 9, now),
|
||||
Texture::new(&HEALPixCell(0, 10), 10, now),
|
||||
Texture::new(&HEALPixCell(0, 11), 11, now),
|
||||
];*/
|
||||
];
|
||||
let channel = config.get_format().get_channel();
|
||||
|
||||
#[cfg(feature = "webgl2")]
|
||||
let texture_2d_array = match channel {
|
||||
ChannelType::RGBA32F => unimplemented!(),
|
||||
ChannelType::RGB32F => unimplemented!(),
|
||||
ChannelType::RGBA8U => create_texture_array::<RGBA8U>(gl, &config)?,
|
||||
ChannelType::RGB8U => create_texture_array::<RGB8U>(gl, &config)?,
|
||||
ChannelType::R32F => create_texture_array::<R32F>(gl, &config)?,
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R8UI => create_texture_array::<R8UI>(gl, &config)?,
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R16I => create_texture_array::<R16I>(gl, &config)?,
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R32I => create_texture_array::<R32I>(gl, &config)?,
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R64F => create_texture_array::<R64F>(gl, &config)?,
|
||||
ChannelType::RGBA8U => Rc::new(create_texture_array::<RGBA8U>(gl, &config)?),
|
||||
ChannelType::RGB8U => Rc::new(create_texture_array::<RGB8U>(gl, &config)?),
|
||||
ChannelType::R8UI => Rc::new(create_texture_array::<R8UI>(gl, &config)?),
|
||||
ChannelType::R16I => Rc::new(create_texture_array::<R16I>(gl, &config)?),
|
||||
ChannelType::R32I => Rc::new(create_texture_array::<R32I>(gl, &config)?),
|
||||
ChannelType::R32F => Rc::new(create_texture_array::<R32F>(gl, &config)?),
|
||||
ChannelType::R64F => Rc::new(create_texture_array::<R64F>(gl, &config)?),
|
||||
};
|
||||
#[cfg(feature = "webgl1")]
|
||||
let texture_2d_array = match config.get_format() {
|
||||
ChannelType::RGBA32F => unimplemented!(),
|
||||
ChannelType::RGB32F => unimplemented!(),
|
||||
ChannelType::RGBA8U => Rc::new(create_texture_array::<RGBA8U>(gl, &config)?),
|
||||
ChannelType::RGB8U => Rc::new(create_texture_array::<RGB8U>(gl, &config)?),
|
||||
ChannelType::R32F => Rc::new(create_texture_array::<R32F>(gl, &config)?),
|
||||
};
|
||||
|
||||
// The root textures have not been loaded
|
||||
//let ready = false;
|
||||
//let num_root_textures_available = 0;
|
||||
let available_tiles_during_frame = false;
|
||||
let start_time = None;
|
||||
//let num_base_textures = 0;
|
||||
Ok(ImageSurveyTextures {
|
||||
config,
|
||||
heap,
|
||||
@@ -226,8 +228,8 @@ impl ImageSurveyTextures {
|
||||
size,
|
||||
//num_root_textures_available,
|
||||
textures,
|
||||
//base_textures,
|
||||
//num_base_textures,
|
||||
base_textures,
|
||||
|
||||
texture_2d_array,
|
||||
available_tiles_during_frame,
|
||||
|
||||
@@ -244,21 +246,21 @@ impl ImageSurveyTextures {
|
||||
self.texture_2d_array = match channel {
|
||||
ChannelType::RGBA32F => unimplemented!(),
|
||||
ChannelType::RGB32F => unimplemented!(),
|
||||
ChannelType::RGBA8U => create_texture_array::<RGBA8U>(gl, &self.config)?,
|
||||
ChannelType::RGB8U => create_texture_array::<RGB8U>(gl, &self.config)?,
|
||||
ChannelType::R32F => create_texture_array::<R32F>(gl, &self.config)?,
|
||||
ChannelType::RGBA8U => Rc::new(create_texture_array::<RGBA8U>(gl, &self.config)?),
|
||||
ChannelType::RGB8U => Rc::new(create_texture_array::<RGB8U>(gl, &self.config)?),
|
||||
ChannelType::R32F => Rc::new(create_texture_array::<R32F>(gl, &self.config)?),
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R8UI => create_texture_array::<R8UI>(gl, &self.config)?,
|
||||
ChannelType::R8UI => Rc::new(create_texture_array::<R8UI>(gl, &self.config)?),
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R16I => create_texture_array::<R16I>(gl, &self.config)?,
|
||||
ChannelType::R16I => Rc::new(create_texture_array::<R16I>(gl, &self.config)?),
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R32I => create_texture_array::<R32I>(gl, &self.config)?,
|
||||
ChannelType::R32I => Rc::new(create_texture_array::<R32I>(gl, &self.config)?),
|
||||
#[cfg(feature = "webgl2")]
|
||||
ChannelType::R64F => create_texture_array::<R64F>(gl, &self.config)?,
|
||||
ChannelType::R64F => Rc::new(create_texture_array::<R64F>(gl, &self.config)?),
|
||||
};
|
||||
|
||||
let now = Time::now();
|
||||
/*self.base_textures = [
|
||||
self.base_textures = [
|
||||
Texture::new(&HEALPixCell(0, 0), 0, now),
|
||||
Texture::new(&HEALPixCell(0, 1), 1, now),
|
||||
Texture::new(&HEALPixCell(0, 2), 2, now),
|
||||
@@ -271,7 +273,7 @@ impl ImageSurveyTextures {
|
||||
Texture::new(&HEALPixCell(0, 9), 9, now),
|
||||
Texture::new(&HEALPixCell(0, 10), 10, now),
|
||||
Texture::new(&HEALPixCell(0, 11), 11, now),
|
||||
];*/
|
||||
];
|
||||
|
||||
self.heap.clear();
|
||||
self.textures.clear();
|
||||
@@ -324,7 +326,7 @@ impl ImageSurveyTextures {
|
||||
let tex_cell = cell.get_texture_cell(self.config.delta_depth());
|
||||
|
||||
let tex_cell_is_root = tex_cell.is_root(self.config.delta_depth());
|
||||
if !self.textures.contains_key(&tex_cell) {
|
||||
if !tex_cell_is_root && !self.textures.contains_key(&tex_cell) {
|
||||
// The texture is not among the essential ones
|
||||
// (i.e. is not a root texture)
|
||||
let texture = if self.is_heap_full() {
|
||||
@@ -338,12 +340,6 @@ impl ImageSurveyTextures {
|
||||
"Texture (oldest one) has not been found in the buffer of textures",
|
||||
);
|
||||
// Clear and assign it to tex_cell
|
||||
/*let idx = if tex_cell_is_root {
|
||||
self.num_base_textures += 1;
|
||||
Some(tex_cell.idx() as i32)
|
||||
} else {
|
||||
None
|
||||
};*/
|
||||
texture.replace(&tex_cell, time_request);
|
||||
|
||||
texture
|
||||
@@ -351,18 +347,10 @@ impl ImageSurveyTextures {
|
||||
// The heap buffer is not full, let's create a new
|
||||
// texture with an unique idx
|
||||
// The idx is computed based on the current size of the buffer
|
||||
/*let idx = if tex_cell_is_root {
|
||||
self.num_base_textures += 1;
|
||||
tex_cell.idx() as usize
|
||||
} else {
|
||||
//NUM_HPX_TILES_DEPTH_ZERO + (self.heap.len() - self.num_base_textures)
|
||||
self.heap.len()
|
||||
};*/
|
||||
let idx = self.heap.len();
|
||||
let idx = NUM_HPX_TILES_DEPTH_ZERO + self.heap.len();
|
||||
|
||||
Texture::new(&tex_cell, idx as i32, time_request)
|
||||
};
|
||||
|
||||
// Push it to the buffer
|
||||
self.heap.push(&texture);
|
||||
|
||||
@@ -375,17 +363,23 @@ impl ImageSurveyTextures {
|
||||
// We can safely push it
|
||||
// First get the texture
|
||||
|
||||
let texture = //if !tex_cell_is_root {
|
||||
let texture = if !tex_cell_is_root {
|
||||
self.textures
|
||||
.get_mut(&tex_cell)
|
||||
.expect("the cell has to be in the tile buffer");
|
||||
/* } else {
|
||||
.expect("the cell has to be in the tile buffer")
|
||||
} else {
|
||||
let HEALPixCell(_, idx) = tex_cell;
|
||||
&mut self.base_textures[idx as usize]
|
||||
};*/
|
||||
};
|
||||
|
||||
if let Some(image) = image {
|
||||
send_to_gpu(cell, texture, image, &self.texture_2d_array, &self.config)?;
|
||||
send_to_gpu(
|
||||
cell,
|
||||
texture,
|
||||
image,
|
||||
self.texture_2d_array.clone(),
|
||||
&self.config,
|
||||
)?;
|
||||
// Once the texture has been received in the GPU
|
||||
texture.append(
|
||||
cell, // The tile cell
|
||||
@@ -397,7 +391,7 @@ impl ImageSurveyTextures {
|
||||
cell,
|
||||
texture,
|
||||
self.config.get_default_image(),
|
||||
&self.texture_2d_array,
|
||||
self.texture_2d_array.clone(),
|
||||
&self.config,
|
||||
)?;
|
||||
// Once the texture has been received in the GPU
|
||||
@@ -410,9 +404,9 @@ impl ImageSurveyTextures {
|
||||
|
||||
self.available_tiles_during_frame = true;
|
||||
//self.ready = true;
|
||||
/*if self.start_time.is_none() {
|
||||
if self.start_time.is_none() {
|
||||
self.start_time = Some(Time::now());
|
||||
}*/
|
||||
}
|
||||
|
||||
/*if tex_cell.is_root(self.config.delta_depth()) && texture.is_available() {
|
||||
self.num_root_textures_available += 1;
|
||||
@@ -442,15 +436,23 @@ impl ImageSurveyTextures {
|
||||
// textures in the buffer
|
||||
let num_textures_heap = self.heap.len();
|
||||
|
||||
num_textures_heap == self.size
|
||||
num_textures_heap == (self.size - NUM_HPX_TILES_DEPTH_ZERO)
|
||||
}
|
||||
|
||||
// Tell if a texture is available meaning all its sub tiles
|
||||
// must have been written for the GPU
|
||||
pub fn contains(&self, texture_cell: &HEALPixCell) -> bool {
|
||||
if let Some(t) = self.get(texture_cell) {
|
||||
t.is_full()
|
||||
if let Some(texture) = self.textures.get(texture_cell) {
|
||||
// The texture is in the buffer i.e. there is at least one
|
||||
// sub tile received
|
||||
|
||||
// It is possible that it is not available. Available means
|
||||
// all its sub tiles have been received and written to the
|
||||
// textures array!
|
||||
texture.is_available()
|
||||
} else {
|
||||
// The texture is not contained in the buffer i.e.
|
||||
// even not one sub tile that has been received
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -461,20 +463,20 @@ impl ImageSurveyTextures {
|
||||
pub fn contains_tile(&self, cell: &HEALPixCell) -> bool {
|
||||
let texture_cell = cell.get_texture_cell(self.config.delta_depth());
|
||||
|
||||
//let tex_cell_is_root = texture_cell.is_root(self.config.delta_depth());
|
||||
//if tex_cell_is_root {
|
||||
// let HEALPixCell(_, idx) = texture_cell;
|
||||
// self.base_textures[idx as usize].contains(cell)
|
||||
//} else {
|
||||
if let Some(texture) = self.get(&texture_cell) {
|
||||
// The texture is present in the buffer
|
||||
// We must check whether it contains the tile
|
||||
texture.contains(cell)
|
||||
let tex_cell_is_root = texture_cell.is_root(self.config.delta_depth());
|
||||
if tex_cell_is_root {
|
||||
let HEALPixCell(_, idx) = texture_cell;
|
||||
self.base_textures[idx as usize].contains(cell)
|
||||
} else {
|
||||
// The texture in which cell should be is not present
|
||||
false
|
||||
if let Some(texture) = self.textures.get(&texture_cell) {
|
||||
// The texture is present in the buffer
|
||||
// We must check whether it contains the tile
|
||||
texture.contains(cell)
|
||||
} else {
|
||||
// The texture in which cell should be is not present
|
||||
false
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
// Update the priority of the texture containing the tile
|
||||
@@ -484,9 +486,9 @@ impl ImageSurveyTextures {
|
||||
|
||||
// Get the texture cell in which the tile has to be
|
||||
let texture_cell = cell.get_texture_cell(self.config.delta_depth());
|
||||
//if texture_cell.is_root(self.config().delta_depth()) {
|
||||
// return;
|
||||
//}
|
||||
if texture_cell.is_root(self.config().delta_depth()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let texture = self
|
||||
.textures
|
||||
@@ -518,7 +520,7 @@ impl ImageSurveyTextures {
|
||||
let (pix, dx, dy) = crate::healpix::utils::hash_with_dxdy(depth, lonlat);
|
||||
let texture_cell = HEALPixCell(depth, pix);
|
||||
|
||||
if let Some(texture) = self.get(&texture_cell) {
|
||||
if let Some(texture) = self.textures.get(&texture_cell) {
|
||||
let cfg = &self.config;
|
||||
|
||||
// Index of the texture in the total set of textures
|
||||
@@ -566,33 +568,29 @@ impl ImageSurveyTextures {
|
||||
|
||||
/// Accessors
|
||||
pub fn get(&self, texture_cell: &HEALPixCell) -> Option<&Texture> {
|
||||
//if texture_cell.is_root(self.config().delta_depth()) {
|
||||
// let HEALPixCell(_, idx) = texture_cell;
|
||||
// Some(&self.base_textures[*idx as usize])
|
||||
//} else {
|
||||
self.textures.get(texture_cell)
|
||||
//}
|
||||
if texture_cell.is_root(self.config().delta_depth()) {
|
||||
let HEALPixCell(_, idx) = texture_cell;
|
||||
Some(&self.base_textures[*idx as usize])
|
||||
} else {
|
||||
self.textures.get(texture_cell)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the nearest parent tile found in the CPU buffer
|
||||
pub fn get_nearest_parent(&self, cell: &HEALPixCell) -> Option<HEALPixCell> {
|
||||
pub fn get_nearest_parent(&self, cell: &HEALPixCell) -> HEALPixCell {
|
||||
let dd = self.config.delta_depth();
|
||||
/*if cell.is_root(dd) {
|
||||
if cell.is_root(dd) {
|
||||
// Root cells are in the buffer by definition
|
||||
*cell
|
||||
} else {*/
|
||||
let mut parent_cell = cell.parent();
|
||||
|
||||
while !self.contains(&parent_cell) && !parent_cell.is_root(dd) {
|
||||
parent_cell = parent_cell.parent();
|
||||
}
|
||||
|
||||
if self.contains(&parent_cell) {
|
||||
Some(parent_cell)
|
||||
} else {
|
||||
None
|
||||
let mut parent_cell = cell.parent();
|
||||
|
||||
while !self.contains(&parent_cell) && !parent_cell.is_root(dd) {
|
||||
parent_cell = parent_cell.parent();
|
||||
}
|
||||
|
||||
parent_cell
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
pub fn config(&self) -> &HiPSConfig {
|
||||
@@ -630,8 +628,8 @@ impl ImageSurveyTextures {
|
||||
]
|
||||
}*/
|
||||
|
||||
pub fn get_texture_array(&self) -> &Texture2DArray {
|
||||
&self.texture_2d_array
|
||||
pub fn get_texture_array(&self) -> Rc<Texture2DArray> {
|
||||
self.texture_2d_array.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,7 +637,7 @@ fn send_to_gpu<I: Image>(
|
||||
cell: &HEALPixCell,
|
||||
texture: &Texture,
|
||||
image: I,
|
||||
texture_array: &Texture2DArray,
|
||||
texture_array: Rc<Texture2DArray>,
|
||||
cfg: &HiPSConfig,
|
||||
) -> Result<(), JsValue> {
|
||||
// Index of the texture in the total set of textures
|
||||
@@ -679,30 +677,17 @@ impl SendUniforms for ImageSurveyTextures {
|
||||
// Send only the allsky textures
|
||||
fn attach_uniforms<'a>(&self, shader: &'a ShaderBound<'a>) -> &'a ShaderBound<'a> {
|
||||
// Send the textures
|
||||
/*let textures = &self.base_textures;
|
||||
let textures = &self.base_textures;
|
||||
for (idx, texture) in textures.iter().enumerate() {
|
||||
let texture_uniforms = TextureUniforms::new(texture, idx as i32);
|
||||
shader.attach_uniforms_from(&texture_uniforms);
|
||||
}*/
|
||||
|
||||
//if self.raytracing {
|
||||
for idx in 0..NUM_HPX_TILES_DEPTH_ZERO {
|
||||
let cell = HEALPixCell(0, idx as u64);
|
||||
|
||||
if let Some(texture) = self.get(&cell) {
|
||||
let texture_uniforms = TextureUniforms::new(texture, idx as i32);
|
||||
shader.attach_uniforms_from(&texture_uniforms);
|
||||
} else {
|
||||
let texture = &Texture::new(&cell, idx as i32, Time::now());
|
||||
let texture_uniforms = TextureUniforms::new(texture, idx as i32);
|
||||
shader.attach_uniforms_from(&texture_uniforms);
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
let num_tiles = textures.len() as i32;
|
||||
let shader = shader
|
||||
.attach_uniform("num_tiles", &num_tiles)
|
||||
.attach_uniforms_from(&self.config)
|
||||
.attach_uniforms_from(&self.texture_2d_array);
|
||||
.attach_uniforms_from(&*self.texture_2d_array);
|
||||
|
||||
shader
|
||||
}
|
||||
|
||||
@@ -168,8 +168,8 @@ pub struct HiPSConfig {
|
||||
pub frame: CooSystem,
|
||||
pub bitpix: Option<i32>,
|
||||
format: ImageFormatType,
|
||||
//dataproduct_subtype: Option<Vec<String>>,
|
||||
//colored: bool,
|
||||
dataproduct_subtype: Option<Vec<String>>,
|
||||
colored: bool,
|
||||
pub creator_did: String,
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ use wasm_bindgen::JsValue;
|
||||
|
||||
const NUM_TEXTURES_BY_SIDE_SLICE: i32 = 8;
|
||||
const NUM_TEXTURES_BY_SLICE: i32 = NUM_TEXTURES_BY_SIDE_SLICE * NUM_TEXTURES_BY_SIDE_SLICE;
|
||||
const NUM_SLICES: i32 = 2;
|
||||
const NUM_SLICES: i32 = 1;
|
||||
|
||||
impl HiPSConfig {
|
||||
/// Define a HiPS configuration
|
||||
@@ -272,7 +272,7 @@ impl HiPSConfig {
|
||||
}),
|
||||
}?;
|
||||
|
||||
/*let dataproduct_subtype = properties.get_dataproduct_subtype().clone();
|
||||
let dataproduct_subtype = properties.get_dataproduct_subtype().clone();
|
||||
let colored = if tex_storing_fits {
|
||||
false
|
||||
} else {
|
||||
@@ -281,7 +281,7 @@ impl HiPSConfig {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};*/
|
||||
};
|
||||
|
||||
let empty_image = EmptyTileImage::new(tile_size, format.get_channel());
|
||||
|
||||
@@ -341,8 +341,8 @@ impl HiPSConfig {
|
||||
bitpix,
|
||||
format,
|
||||
tile_size,
|
||||
//dataproduct_subtype,
|
||||
//colored,
|
||||
dataproduct_subtype,
|
||||
colored,
|
||||
};
|
||||
|
||||
Ok(hips_config)
|
||||
@@ -421,7 +421,7 @@ impl HiPSConfig {
|
||||
self.empty_image = EmptyTileImage::new(self.tile_size, self.format.get_channel());
|
||||
|
||||
// Recompute if the survey will be colored or not
|
||||
/*self.colored = if self.tex_storing_fits {
|
||||
self.colored = if self.tex_storing_fits {
|
||||
false
|
||||
} else {
|
||||
if let Some(subtypes) = &self.dataproduct_subtype {
|
||||
@@ -429,7 +429,7 @@ impl HiPSConfig {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};*/
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -528,7 +528,7 @@ impl HiPSConfig {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_colored(&self) -> bool {
|
||||
self.format.is_colored()
|
||||
self.colored
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
@@ -105,10 +105,14 @@ impl Texture {
|
||||
self.full
|
||||
}
|
||||
|
||||
pub fn is_available(&self) -> bool {
|
||||
self.is_full()
|
||||
}
|
||||
|
||||
// Getter
|
||||
// Returns the current time if the texture is not full
|
||||
pub fn start_time(&self) -> Time {
|
||||
if self.is_full() {
|
||||
if self.is_available() {
|
||||
self.start_time.unwrap_abort()
|
||||
} else {
|
||||
Time::now()
|
||||
|
||||
@@ -92,7 +92,6 @@ impl TileFetcherQueue {
|
||||
// Try to fetch the MOC
|
||||
downloader.fetch(query::Moc::new(
|
||||
format!("{}/Moc.fits", cfg.get_root_url()),
|
||||
cfg.get_creator_did().to_string(),
|
||||
al_api::moc::MOC::default(),
|
||||
));
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
body { overscroll-behavior: contain; }
|
||||
|
||||
.aladin-container {
|
||||
position: relative;
|
||||
border: 0px solid #ddd;
|
||||
/* SVG inside divs add a 4px height: https://stackoverflow.com/questions/75751593/why-there-is-additional-4px-height-for-div-when-there-is-svg-inside-it */
|
||||
border: 1px solid #ddd;
|
||||
height: 100%;
|
||||
|
||||
/* disable x swipe on chrome, firefox */
|
||||
/* see. https://stackoverflow.com/questions/30636930/disable-web-page-navigation-on-swipeback-and-forward */
|
||||
overscroll-behavior-x: none;
|
||||
|
||||
/* media query on the aladin lite container. not supported everywhere.
|
||||
There can be a more supported alternative here: https://caniuse.com/?search=grid-template-columns */
|
||||
/*container-type: inline-size;*/
|
||||
}
|
||||
|
||||
.aladin-imageCanvas {
|
||||
position: absolute;
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
@@ -77,7 +80,7 @@
|
||||
|
||||
display: block;
|
||||
|
||||
max-height: 30vh;
|
||||
max-height: 15em;
|
||||
max-width: 100%;
|
||||
-ms-overflow-style: none;
|
||||
overscroll-behavior-x: none;
|
||||
@@ -112,7 +115,6 @@
|
||||
|
||||
.aladin-measurement-div.aladin-dark-theme table thead {
|
||||
background-color: #000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.aladin-measurement-div table td.aladin-href-td-container a:hover {
|
||||
@@ -148,8 +150,8 @@
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
/*max-width: 150px;
|
||||
text-overflow: ellipsis;*/
|
||||
max-width: 150px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.aladin-measurement-div table td.aladin-text-td-container {
|
||||
@@ -157,8 +159,8 @@
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
/*max-width: 150px;
|
||||
text-overflow: ellipsis;*/
|
||||
max-width: 150px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.aladin-measurement-div table td.aladin-href-td-container:hover {
|
||||
@@ -242,6 +244,8 @@
|
||||
}
|
||||
|
||||
.aladin-box {
|
||||
display: none;
|
||||
|
||||
padding: 0.2rem;
|
||||
background: whitesmoke;
|
||||
border-radius: 2px;
|
||||
@@ -266,6 +270,26 @@
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.aladin-box::-webkit-scrollbar {
|
||||
display: none; /* for Chrome, Safari, and Opera */
|
||||
}
|
||||
|
||||
.aladin-dialog {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: #eee;
|
||||
border-radius: 4px;
|
||||
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
|
||||
line-height: 1.3;
|
||||
color: #222;
|
||||
max-width: 500px;
|
||||
padding: 0.8em;
|
||||
}
|
||||
|
||||
|
||||
canvas {
|
||||
image-rendering: optimizeSpeed; /* Older versions of FF */
|
||||
image-rendering: -moz-crisp-edges; /* FF 6.0+ */
|
||||
@@ -410,9 +434,6 @@ canvas {
|
||||
.aladin-measurement-div.aladin-dark-theme {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.aladin-measurement-div.aladin-dark-theme table {
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -448,11 +469,11 @@ canvas {
|
||||
}
|
||||
|
||||
.aladin-input-text.aladin-dark-theme.search {
|
||||
width: 14rem;
|
||||
width: 15rem;
|
||||
text-shadow: 0px 0px 2px #000;
|
||||
}
|
||||
|
||||
.aladin-input-text.aladin-dark-theme.search:focus, .aladin-input-text.aladin-dark-theme.search:hover {
|
||||
.aladin-input-text.aladin-dark-theme.search:focus {
|
||||
background-image: url(../../assets/icons/search-white.svg);
|
||||
background-size: 1.8rem;
|
||||
background-repeat: no-repeat;
|
||||
@@ -462,15 +483,16 @@ canvas {
|
||||
.aladin-input-text.search {
|
||||
background-image:none;
|
||||
text-indent: 0rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.aladin-input-text.search.aladin-unknownObject {
|
||||
-webkit-box-shadow:inset 0px 0px 0px 1px #f00;
|
||||
-moz-box-shadow:inset 0px 0px 0px 1px #f00;
|
||||
box-shadow:inset 0px 0px 0px 1px #f00;
|
||||
-webkit-box-shadow:inset 0px 0px 0px 3px #f00;
|
||||
-moz-box-shadow:inset 0px 0px 0px 3px #f00;
|
||||
box-shadow:inset 0px 0px 0px 3px #f00;
|
||||
}
|
||||
|
||||
border: 1px solid red;
|
||||
.aladin-dark-theme {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.aladin-cancelBtn {
|
||||
@@ -654,14 +676,10 @@ canvas {
|
||||
.aladin-status-bar-message {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
text-wrap: nowrap;
|
||||
-ms-overflow-style: none;
|
||||
overscroll-behavior-x: none;
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: none;
|
||||
|
||||
max-width: 20rem;
|
||||
max-width: 300px;
|
||||
|
||||
font-size: 1rem;
|
||||
}
|
||||
@@ -723,6 +741,8 @@ canvas {
|
||||
.aladin-context-sub-menu,
|
||||
.aladin-context-menu {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
|
||||
font-family: monospace;
|
||||
width: max-content;
|
||||
@@ -749,9 +769,10 @@ canvas {
|
||||
padding: 0.2rem 0.4rem;
|
||||
position: relative;
|
||||
|
||||
box-shadow:inset 1px 1px 0px 0px #fff;
|
||||
color: lightgray;
|
||||
background-color: black;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
box-shadow:inset 1px 1px 0px 0px #fff;
|
||||
}
|
||||
|
||||
.aladin-context-menu .aladin-context-menu-item:first-of-type {
|
||||
@@ -964,10 +985,6 @@ canvas {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.aladin-dark-theme {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
|
||||
/* Tooltip */
|
||||
@@ -977,27 +994,22 @@ canvas {
|
||||
/* take the size of its inner div child */
|
||||
|
||||
font-family: monospace;
|
||||
line-height: 1rem;
|
||||
|
||||
|
||||
float: left;
|
||||
}
|
||||
|
||||
.aladin-tooltip-container .aladin-tooltip {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
visibility: hidden;
|
||||
background-color: white;
|
||||
color: black;
|
||||
background-color: black;
|
||||
|
||||
width: max-content;
|
||||
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
border-radius: 2px;
|
||||
|
||||
top:0%;
|
||||
left:0%;
|
||||
|
||||
z-index: 100;
|
||||
|
||||
@@ -1006,13 +1018,6 @@ canvas {
|
||||
|
||||
/*font-family: Verdana, Geneva, Tahoma, sans-serif;*/
|
||||
font-size: 0.9rem;
|
||||
|
||||
transition-delay: 100ms;
|
||||
}
|
||||
|
||||
.aladin-tooltip-container .aladin-tooltip.aladin-dark-theme {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Show the tooltip text when you mouse over the tooltip container */
|
||||
@@ -1072,42 +1077,35 @@ canvas {
|
||||
cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEIEwUMBS20MQAAApRJREFUWEfdV7GO2zAMfXY7x1luzOFwDeB/KHCAB87eumvqmI/JWhTwF3TIrMFAv8JbgWyHG3IpOjbpcKJC02KipECHclIU+j2KfKRlAABRUyFYak3UgKiZiXUJAIt1d1ysu2PYn53DsPCucpbkRE3JAdxKTtQgWo6zJAfGGbAwLuEV7OB9/yrXIbqZ9/0+rMuhdb+RYfWmm+fged8fihzyoXXxlNcYB2KRxwwA6SzI9Crgd973B/5/u3IF8FYSw98M5D2QR86kRE3pfX+AMqKm8iEQoqYaWrfj/4bW7QgokMhCeSs5KeVrDM4K29C6Y6oE0YGEUlndocVGyg/rGZDXBQpr0kmjLiAlOOvk3vf7RJZM5Q+te2W/7coVEq+wnC1yCZYyS3B8MMYF3vBKK9Jz5PWmm8sab1eu4N9D63aaHEAsH88SzmQpnSHsHDmnWvlXIoiJ4JTviY8FRUJ8ZAiOEiJbLpcjARM1M0twpmjZOeGQrXYm1/7yMLz/eH8fnyus6XXOtmLgWBrKtdMguNKYPPystIausn9egsVDfI674KxS6003F/sX357AdOBwcADwWD9EjBKJubxYd0cml4RhP5IPrduFk04GjiZXMyZiRHKdAU3OWeB2lLNAk+tpl9IHY0zSlBo4OgsaTJpFzs+F0pxKYEXK73Nd8+3KFfWmG71qGfgSeQqPN0fvdlZrSvmUoXaJJ7EiocArZaS6tgzA+5RQe3gumUl5gPLXzy+6pEQNzDuhvFKx1ZuuEuTxliwmY/KuoHxGhzGv5QDw9PTx7senz88aLHUpJeOu8OHb17u+//4CTMm97/eFVQK5vqR8y6xOyipByjn3+0C3moUH4O++D1UX3PR9eJWzJCf6Tz5O/wDUeIfTLPlbywAAAABJRU5ErkJggg==') 15 15, auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aladin Lite pre-defined UI features.
|
||||
*
|
||||
* User may need to overwrite those classes if they want
|
||||
* change their position. They can also add media query on them.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Aladin Lite pre-defined UI features */
|
||||
.aladin-stack-control {
|
||||
position: absolute;
|
||||
top: 3rem;
|
||||
left: 0.2rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.aladin-settings-control {
|
||||
position: absolute;
|
||||
top: 5.4rem;
|
||||
left: 0.2rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.aladin-simbadPointer-control {
|
||||
position: absolute;
|
||||
top: 7.8rem;
|
||||
left: 0.2rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.aladin-grid-control {
|
||||
position: absolute;
|
||||
top: 10.2rem;
|
||||
left: 0.2rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.aladin-cooFrame {
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
left: 0.2rem;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
font-family: monospace;
|
||||
|
||||
@@ -1120,8 +1118,8 @@ canvas {
|
||||
|
||||
.aladin-location {
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
left: 6.9rem;
|
||||
top: 0;
|
||||
left: 7rem;
|
||||
font-family: monospace;
|
||||
|
||||
color: white;
|
||||
@@ -1133,61 +1131,40 @@ canvas {
|
||||
|
||||
.aladin-fov {
|
||||
position: absolute;
|
||||
bottom: 0.2rem;
|
||||
left: 0.2rem;
|
||||
top: 0;
|
||||
left: 25rem;
|
||||
|
||||
font-family: monospace;
|
||||
|
||||
color: white;
|
||||
|
||||
font-size: 1rem;
|
||||
border-radius: 5px;
|
||||
line-height: 1.7rem;
|
||||
height: 1.7rem;
|
||||
}
|
||||
|
||||
.aladin-status-bar {
|
||||
border-radius: 3px;
|
||||
padding: 0.4rem;
|
||||
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.aladin-status-bar.aladin-dark-theme {
|
||||
color: white;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.aladin-fov.aladin-dark-theme {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.aladin-table {
|
||||
position: absolute;
|
||||
bottom: 2.8rem;
|
||||
left: 0.2rem;
|
||||
max-width: calc(100% - 0.4rem);
|
||||
line-height: 1rem;
|
||||
}
|
||||
.aladin-measurement-div.aladin-dark-theme {
|
||||
color: white;
|
||||
transform: translate(-50%, 0%);
|
||||
}
|
||||
|
||||
.aladin-share-control {
|
||||
position: absolute;
|
||||
top: 12.6rem;
|
||||
left: 0.2rem;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.aladin-fullScreen-control {
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
right: 0.2rem;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.aladin-projection-control {
|
||||
position: absolute;
|
||||
top: 0.2rem;
|
||||
top: 0;
|
||||
right: 3rem;
|
||||
}
|
||||
|
||||
@@ -1203,6 +1180,8 @@ canvas {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Media query */
|
||||
/*@media screen and (max-width: 31rem) {
|
||||
.aladin-projection-control {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//const int MAX_NUM_TEX = 3;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
//uniform sampler2D tex3;
|
||||
uniform sampler2D tex3;
|
||||
|
||||
uniform int num_tex;
|
||||
|
||||
@@ -23,16 +23,16 @@ uniform int tex_storing_fits;
|
||||
#include ./hsv.glsl;
|
||||
|
||||
vec4 get_pixels(vec3 uv) {
|
||||
|
||||
/*if (idx_texture == 0) {
|
||||
int idx_texture = int(uv.z);
|
||||
if (idx_texture == 0) {
|
||||
return texture(tex1, uv.xy);
|
||||
} else if (idx_texture == 1) {
|
||||
return texture(tex2, uv.xy);
|
||||
} else if (idx_texture == 2) {
|
||||
return texture(tex3, uv.xy);
|
||||
} else {
|
||||
return vec4(0.0, 1.0, 0.0, 1.0);
|
||||
}*/
|
||||
int idx_texture = int(uv.z);
|
||||
return mix(texture(tex1, uv.xy), texture(tex2, uv.xy), float(idx_texture));
|
||||
}
|
||||
}
|
||||
|
||||
vec3 reverse_uv(vec3 uv) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//const int MAX_NUM_TEX = 3;
|
||||
uniform isampler2D tex1;
|
||||
uniform isampler2D tex2;
|
||||
//uniform isampler2D tex3;
|
||||
uniform isampler2D tex3;
|
||||
uniform int num_tex;
|
||||
|
||||
uniform float scale;
|
||||
@@ -22,7 +22,7 @@ uniform int tex_storing_fits;
|
||||
#include ./tonal_corrections.glsl;
|
||||
|
||||
ivec4 get_pixels(vec3 uv) {
|
||||
/*int idx_texture = int(uv.z);
|
||||
int idx_texture = int(uv.z);
|
||||
if (idx_texture == 0) {
|
||||
return texture(tex1, uv.xy);
|
||||
} else if (idx_texture == 1) {
|
||||
@@ -31,10 +31,7 @@ ivec4 get_pixels(vec3 uv) {
|
||||
return texture(tex3, uv.xy);
|
||||
} else {
|
||||
return ivec4(0, 0, 0, 1);
|
||||
}*/
|
||||
//return texture(tex1, uv.xy);
|
||||
int idx_texture = int(uv.z);
|
||||
return ivec4(mix(vec4(texture(tex1, uv.xy)), vec4(texture(tex2, uv.xy)), float(idx_texture)));
|
||||
}
|
||||
}
|
||||
|
||||
vec3 reverse_uv(vec3 uv) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//const int MAX_NUM_TEX = 3;
|
||||
uniform usampler2D tex1;
|
||||
uniform usampler2D tex2;
|
||||
//uniform usampler2D tex3;
|
||||
uniform usampler2D tex3;
|
||||
uniform int num_tex;
|
||||
|
||||
uniform float scale;
|
||||
@@ -22,7 +22,7 @@ uniform int tex_storing_fits;
|
||||
#include ./tonal_corrections.glsl;
|
||||
|
||||
uvec4 get_pixels(vec3 uv) {
|
||||
/*int idx_texture = int(uv.z);
|
||||
int idx_texture = int(uv.z);
|
||||
if (idx_texture == 0) {
|
||||
return texture(tex1, uv.xy);
|
||||
} else if (idx_texture == 1) {
|
||||
@@ -31,11 +31,7 @@ uvec4 get_pixels(vec3 uv) {
|
||||
return texture(tex3, uv.xy);
|
||||
} else {
|
||||
return uvec4(0, 0, 0, 1);
|
||||
}*/
|
||||
//return texture(tex1, uv.xy);
|
||||
//int idx_texture = int(uv.z);
|
||||
int idx_texture = int(uv.z);
|
||||
return uvec4(mix(vec4(texture(tex1, uv.xy)), vec4(texture(tex2, uv.xy)), float(idx_texture)));
|
||||
}
|
||||
}
|
||||
|
||||
vec3 reverse_uv(vec3 uv) {
|
||||
|
||||
@@ -17,6 +17,7 @@ struct Tile {
|
||||
};
|
||||
|
||||
uniform Tile textures_tiles[12];
|
||||
uniform int num_tiles;
|
||||
|
||||
#include ../color.glsl;
|
||||
#include ./healpix.glsl;
|
||||
@@ -28,6 +29,7 @@ vec4 get_tile_color(vec3 pos) {
|
||||
|
||||
int idx = result.idx;
|
||||
vec2 uv = vec2(result.dy, result.dx);
|
||||
|
||||
Tile tile = textures_tiles[idx];
|
||||
|
||||
int idx_texture = tile.texture_idx >> 6;
|
||||
@@ -39,7 +41,6 @@ vec4 get_tile_color(vec3 pos) {
|
||||
vec3 UV = vec3(offset, float(idx_texture));
|
||||
|
||||
vec4 color = get_color_from_texture(UV);
|
||||
color.a *= (1.0 - tile.empty);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ vec4 get_tile_color(vec3 pos) {
|
||||
// For empty tiles we set the alpha of the pixel to 0.0
|
||||
// so that what is behind will be plotted
|
||||
color.a *= (1.0 - tile.empty);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
210
src/js/A.js
210
src/js/A.js
@@ -43,9 +43,6 @@ import { Footprint } from './Footprint.js';
|
||||
import { Aladin } from "./Aladin.js";
|
||||
import { ActionButton } from "./gui/Widgets/ActionButton.js";
|
||||
import { Box } from "./gui/Widgets/Box.js";
|
||||
import { AladinUtils } from "./AladinUtils.js";
|
||||
import { Sesame } from "./Sesame.js";
|
||||
|
||||
// Wasm top level import
|
||||
import init, * as module from './../core/pkg';
|
||||
|
||||
@@ -90,7 +87,6 @@ let A = {};
|
||||
*/
|
||||
A.aladin = function (divSelector, options) {
|
||||
let divElement;
|
||||
|
||||
if (!(divSelector instanceof HTMLElement)) {
|
||||
divElement = document.querySelector(divSelector)
|
||||
} else {
|
||||
@@ -99,45 +95,6 @@ A.aladin = function (divSelector, options) {
|
||||
return new Aladin(divElement, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a HiPS image object
|
||||
*
|
||||
* @function
|
||||
* @name A.imageHiPS
|
||||
* @memberof A
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} url - Can be an `url` that refers to a HiPS.
|
||||
* Or it can be a "CDS ID" pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}.
|
||||
* @param {ImageSurveyOptions} [options] - Options describing the survey
|
||||
* @returns {ImageSurvey} - A HiPS image object
|
||||
*/
|
||||
A.imageHiPS = function (id, url, options) {
|
||||
return Aladin.createImageSurvey(
|
||||
id,
|
||||
options && options.name,
|
||||
url,
|
||||
options && options.cooFrame,
|
||||
options && options.maxOrder,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a celestial source object with the given coordinates.
|
||||
*
|
||||
* @function
|
||||
* @name A.imageFITS
|
||||
* @memberof A
|
||||
* @param {string} url - Options describing the fits file. An url is mandatory
|
||||
* @param {ImageFITSOptions} [options] - Options describing the fits file. An url is mandatory
|
||||
* @returns {ImageSurvey} - A HiPS image object
|
||||
* @example
|
||||
* const sourceObj = A.source(180.0, 30.0, data, options);
|
||||
*/
|
||||
A.imageFITS = function (url, options) {
|
||||
return Aladin.createImageFITS(url, options.name, options, options.successCallback, options.errorCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a celestial source object with the given coordinates.
|
||||
*
|
||||
@@ -377,7 +334,6 @@ A.MOCFromPolygon= function (polygon, options, successCallback, errorCallback) {
|
||||
* @property {string} [decField] - The ID or name of the field holding Declination (dec).
|
||||
* @property {function} [filter] - The filtering function for sources. Returns a boolean
|
||||
* @property {boolean} [displayLabel=false] - Whether to display labels for sources.
|
||||
* @property {string} [labelColumn] - The name of the column to be used for the label.
|
||||
* @property {string} [labelColor] - The color of the source labels.
|
||||
* @property {string} [labelFont="10px sans-serif"] - The font for the source labels.
|
||||
*/
|
||||
@@ -503,9 +459,9 @@ A.catalogFromURL = function (url, options, successCallback, errorCallback, usePr
|
||||
* @param {number} target.dec - Declination in degrees of the cone's center
|
||||
* @param {number} radius - Radius of the cone in degrees
|
||||
* @param {Object|CatalogOptions} [options] - Additional configuration options for SIMBAD cone search. See the {@link https://simbad.cds.unistra.fr/cone/help/#/ConeSearch/get_ SIMBAD cone search} parameters.
|
||||
* @param {number} [options.limit] - The max number of sources to return
|
||||
* @param {string} [options.orderBy='nb_ref'] - Order the result by specific ref number
|
||||
* @param {number} [options.verbosity=2] - Verbosity, put 3 if you want all the column
|
||||
* @param {Object} [options.limit] - The max number of sources to return
|
||||
* @param {Object} [options.orderBy] - Order the result by specific
|
||||
*
|
||||
* @param {function} [successCallback] - The callback function to execute on successful catalog creation.
|
||||
* @param {function} [errorCallback] - The callback function to execute on error during catalog creation.
|
||||
* @returns {Catalog} A new instance of the Catalog class created from the SIMBAD cone search.
|
||||
@@ -520,8 +476,8 @@ A.catalogFromSimbad = function (target, radius, options, successCallback, errorC
|
||||
if (!('name' in options)) {
|
||||
options['name'] = 'Simbad';
|
||||
}
|
||||
let cat = A.catalog(options);
|
||||
new Promise((resolve, reject) => {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let coo;
|
||||
if (target && (typeof target === "object")) {
|
||||
if ('ra' in target && 'dec' in target) {
|
||||
@@ -557,45 +513,8 @@ A.catalogFromSimbad = function (target, radius, options, successCallback, errorC
|
||||
}
|
||||
}).then((coo) => {
|
||||
const url = URLBuilder.buildSimbadCSURL(coo.lon, coo.lat, radius, options)
|
||||
const processVOTable = function (table) {
|
||||
let {sources, footprints, fields, type} = table;
|
||||
cat.setFields(fields);
|
||||
|
||||
if (cat.type === 'ObsCore') {
|
||||
// The fields corresponds to obscore ones
|
||||
// Set the name of the catalog to be ObsCore:<catalog name>
|
||||
cat.name = "ObsCore:" + url;
|
||||
}
|
||||
|
||||
cat.addFootprints(footprints)
|
||||
cat.addSources(sources);
|
||||
|
||||
if (successCallback) {
|
||||
successCallback(cat);
|
||||
}
|
||||
|
||||
if (sources.length === 0) {
|
||||
console.warn(cat.name + ' has no sources!')
|
||||
}
|
||||
|
||||
// Even if the votable is not a proper ObsCore one, try to see if specific columns are given
|
||||
// e.g. access_format and access_url
|
||||
//ObsCore.handleActions(catalog);
|
||||
};
|
||||
|
||||
|
||||
Catalog.parseVOTable(
|
||||
url,
|
||||
processVOTable,
|
||||
errorCallback,
|
||||
cat.maxNbSources,
|
||||
false,
|
||||
cat.raField, cat.decField
|
||||
);
|
||||
|
||||
return A.catalogFromURL(url, options, successCallback, errorCallback, false);
|
||||
})
|
||||
|
||||
return cat;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -749,77 +668,39 @@ A.catalogFromSkyBot = function (ra, dec, radius, epoch, queryOptions, options, s
|
||||
* @returns {ActionButton} Returns a new button object representing the graphic overlay.
|
||||
*
|
||||
* @example
|
||||
* <!-- This example instanciates a customized button that when clicked, enters the user in
|
||||
* the polygonal selection mode. Once the polygon selection is done, the vertices are converted
|
||||
* to sky coords and a Multi-Order Coverage (MOC) is created from that list of sky coords. -->
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<div id="aladin-lite-div" style="width: 512px; height: 512px"></div>
|
||||
|
||||
<script type="module">
|
||||
import A from aladin-lite;
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
var aladin = A.aladin(
|
||||
'#aladin-lite-div',
|
||||
{
|
||||
survey: 'P/allWISE/color', // set initial image survey
|
||||
projection: 'AIT', // set a projection
|
||||
fov: 1.5, // initial field of view in degrees
|
||||
target: 'NGC 2175', // initial target
|
||||
cooFrame: 'icrs', // set galactic frame
|
||||
reticleColor: '#ff89ff', // change reticle color
|
||||
reticleSize: 64, // change reticle size
|
||||
showContextMenu: true,
|
||||
}
|
||||
);
|
||||
|
||||
let btn = A.button({
|
||||
content: 'My button',
|
||||
classList: ['myButton'],
|
||||
tooltip: {cssStyle: {color: 'red'}, content: 'Create a moc in pink!', position: {direction: 'top'}},
|
||||
action(o) {
|
||||
aladin.select('poly', p => {
|
||||
try {
|
||||
let ra = []
|
||||
let dec = []
|
||||
for (const v of p.vertices) {
|
||||
let [lon, lat] = aladin.pix2world(v.x, v.y);
|
||||
ra.push(lon)
|
||||
dec.push(lat)
|
||||
}
|
||||
|
||||
let moc = A.MOCFromPolygon(
|
||||
{ra, dec},
|
||||
{name: 'poly', lineWidth: 3.0, color: 'pink'},
|
||||
);
|
||||
aladin.addMOC(moc)
|
||||
} catch(_) {
|
||||
alert('Selection covers a region out of the projection definition domain.');
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
aladin.addUI(btn)
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
.myButton {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
background-color: pink;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
* let btn = A.button({
|
||||
* content: 'Draw your coverage',
|
||||
* cssStyle: {
|
||||
* backgroundColor: 'pink',
|
||||
* },
|
||||
* // Adding a CSS class allowing you to position your button on the aladin lite view
|
||||
* classList: ['myButton'],
|
||||
* tooltip: {cssStyle: {color: 'red'}, content: 'Create a moc in pink!', position: {direction: 'top'}},
|
||||
* action(o) {
|
||||
* // Enter a polygonal selection mode
|
||||
* aladin.select('poly', p => {
|
||||
* // Create a moc from the polygon
|
||||
* try {
|
||||
* let ra = []
|
||||
* let dec = []
|
||||
* for (const v of p.vertices) {
|
||||
* let [lon, lat] = aladin.pix2world(v.x, v.y);
|
||||
* ra.push(lon)
|
||||
* dec.push(lat)
|
||||
* }
|
||||
*
|
||||
* let moc = A.MOCFromPolygon(
|
||||
* {ra, dec},
|
||||
* {name: 'poly', lineWidth: 3.0, color: 'pink'},
|
||||
* );
|
||||
* aladin.addMOC(moc)
|
||||
* } catch(_) {
|
||||
* alert('Selection covers a region out of the projection definition domain.');
|
||||
* }
|
||||
* })
|
||||
* }
|
||||
* });
|
||||
* aladin.addUI(btn)
|
||||
*/
|
||||
A.button = function(options) {
|
||||
return new ActionButton(options);
|
||||
@@ -861,19 +742,6 @@ A.getAvailableListOfColormaps = function() {
|
||||
return ColorCfg.COLORMAPS;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns utils object
|
||||
*
|
||||
* This contains utilitary methods such as HEALPix basic or projection methods.
|
||||
*
|
||||
* @function
|
||||
* @memberof A
|
||||
* @name Utils
|
||||
*
|
||||
* @returns {AladinUtils} Returns a new box window object.
|
||||
*/
|
||||
A.Utils = AladinUtils;
|
||||
|
||||
/**
|
||||
* Initializes the Aladin Lite library, checking for WebGL2 support.
|
||||
* This method must be called before instancing an Aladin Lite object.
|
||||
|
||||
486
src/js/Aladin.js
486
src/js/Aladin.js
@@ -56,32 +56,34 @@ import { Location } from "./gui/Location.js";
|
||||
import { FoV } from "./gui/FoV.js";
|
||||
import { ShareActionButton } from "./gui/Button/ShareView.js";
|
||||
import { ContextMenu } from "./gui/Widgets/ContextMenu.js";
|
||||
import { Input } from "./gui/Widgets/Input.js";
|
||||
import { Popup } from "./Popup.js";
|
||||
import A from "./A.js";
|
||||
import { StatusBarBox } from "./gui/Box/StatusBarBox.js";
|
||||
import { FullScreenActionButton } from "./gui/Button/FullScreen.js";
|
||||
import { ProjectionActionButton } from "./gui/Button/Projection.js";
|
||||
import { Toolbar } from './gui/Widgets/Toolbar';
|
||||
import { ImageLayer } from './ImageLayer';
|
||||
|
||||
// features
|
||||
import { SettingsButton } from "./gui/Button/Settings";
|
||||
import { SimbadPointer } from "./gui/Button/SimbadPointer";
|
||||
import { OverlayStackButton } from "./gui/Button/OverlayStack";
|
||||
import { GridEnabler } from './gui/Button/GridEnabler';
|
||||
import { CooFrame } from './gui/Input/CooFrame';
|
||||
|
||||
/**
|
||||
* @typedef {Object} AladinOptions
|
||||
* @description Options for configuring the Aladin Lite instance.
|
||||
*
|
||||
* @property {string} [survey="CDS/P/DSS2/color"] URL or ID of the survey to use
|
||||
* @property {string[]} [surveyUrl]
|
||||
* @property {string} [survey="https://alaskybis.unistra.fr/DSS/DSSColor"] URL or ID of the survey to use
|
||||
* @property {string[]} [surveyUrl=["https://alaskybis.unistra.fr/DSS/DSSColor", "https://alasky.unistra.fr/DSS/DSSColor"]]
|
||||
* Array of URLs for the survey images. This replaces the survey parameter.
|
||||
* @property {string} [target="0 +0"] - Target coordinates for the initial view.
|
||||
* @property {CooFrame} [cooFrame="J2000"] - Coordinate frame.
|
||||
* @property {string} [cooFrame="J2000"] - Coordinate frame.
|
||||
* @property {number} [fov=60] - Field of view in degrees.
|
||||
* @property {string} [backgroundColor="rgb(60, 60, 60)"] - Background color in RGB format.
|
||||
*
|
||||
* @property {boolean} [showZoomControl=false] - Whether to show the zoom control toolbar.
|
||||
* @property {boolean} [showZoomControl=true] - Whether to show the zoom control toolbar.
|
||||
* This element belongs to the FoV UI thus its CSS class is `aladin-fov`
|
||||
* @property {boolean} [showLayersControl=true] - Whether to show the layers control toolbar.
|
||||
* CSS class for that button is `aladin-stack-control`
|
||||
@@ -127,50 +129,13 @@ import { CooFrame } from './gui/Input/CooFrame';
|
||||
* @property {boolean} [gridOptions.showLabels=true] - Whether the grid has labels.
|
||||
* @property {number} [gridOptions.labelSize=15] - The font size of the labels.
|
||||
*
|
||||
* @property {string} [projection="SIN"] - Projection type. Can be 'SIN' for orthographic, 'MOL' for mollweide, 'AIT' for hammer-aitoff, 'ZEA' for zenital equal-area or 'MER' for mercator
|
||||
* @property {string} [projection="SIN"] - Projection type.
|
||||
* @property {boolean} [log=true] - Whether to log events.
|
||||
* @property {boolean} [samp=false] - Whether to enable SAMP (Simple Application Messaging Protocol).
|
||||
* @property {boolean} [realFullscreen=false] - Whether to use real fullscreen mode.
|
||||
* @property {boolean} [pixelateCanvas=true] - Whether to pixelate the canvas.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CircleSelection
|
||||
* @description Options for configuring the Aladin Lite instance.
|
||||
*
|
||||
* @property {number} x - x coordinate of the center's circle in pixels
|
||||
* @property {number} y - y coordinate of the center's circle in pixels
|
||||
* @property {number} r - radius of the circle in pixels
|
||||
* @property {function} contains - function taking a {x, y} object telling if the vertex is contained or not
|
||||
* @property {function} bbox - returns the bbox of the selection in pixels
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} RectSelection
|
||||
* @description Options for configuring the Aladin Lite instance.
|
||||
*
|
||||
* @property {number} x - top left x coordinate of the rectangle in pixels
|
||||
* @property {number} y - top left y coordinate of the rectangle in pixels
|
||||
* @property {number} w - width of the selection in pixels
|
||||
* @property {number} h - height of the selection in pixels
|
||||
* @property {function} contains - function taking a {x, y} object telling if the vertex is contained in the selection or not
|
||||
* @property {function} bbox - returns the bbox of the selection in pixels
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PolygonSelection
|
||||
* @description Options for configuring the Aladin Lite instance.
|
||||
*
|
||||
* @property {Object[]} vertices - vertices of the polygon selection in pixels. Each vertex has a x and y key in pixels.
|
||||
* @property {function} contains - function taking a {x, y} object telling if the vertex is contained in the selection or not
|
||||
* @property {function} bbox - returns the bbox of the selection in pixels
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {string} CooFrame
|
||||
* String with possible values: 'equatorial', 'ICRS', 'ICRSd', 'j2000', 'gal, 'galactic'
|
||||
*/
|
||||
|
||||
export let Aladin = (function () {
|
||||
/**
|
||||
* Creates an instance of the Aladin interactive sky atlas.
|
||||
@@ -245,12 +210,14 @@ export let Aladin = (function () {
|
||||
this.options = options;
|
||||
|
||||
this.reduceDeformations = true;
|
||||
|
||||
// Init the measurement table
|
||||
this.measurementTable = new MeasurementTable(this);
|
||||
|
||||
// parent div
|
||||
aladinDiv.classList.add("aladin-container");
|
||||
|
||||
// measurement table
|
||||
this.measurementTable = new MeasurementTable(this);
|
||||
|
||||
//var location = new Location(locationDiv.find('.aladin-location-text'));
|
||||
|
||||
// set different options
|
||||
// Reticle
|
||||
this.view = new View(this);
|
||||
@@ -261,6 +228,7 @@ export let Aladin = (function () {
|
||||
this.reticle = new Reticle(this.options, this);
|
||||
this.popup = new Popup(this.aladinDiv, this.view);
|
||||
|
||||
this.cacheSurveys = new Map();
|
||||
this.ui = [];
|
||||
|
||||
// Background color
|
||||
@@ -280,6 +248,10 @@ export let Aladin = (function () {
|
||||
}
|
||||
this.setCooGrid(gridOptions);
|
||||
|
||||
// Set the projection
|
||||
let projection = (options && options.projection) || 'SIN';
|
||||
this.setProjection(projection)
|
||||
|
||||
this.gotoObject(options.target, undefined);
|
||||
|
||||
if (options.log) {
|
||||
@@ -306,14 +278,12 @@ export let Aladin = (function () {
|
||||
i++;
|
||||
});
|
||||
} else if (options.survey === ImageSurvey.DEFAULT_SURVEY_ID) {
|
||||
// DSS is cached inside ImageSurvey class, no need to provide any further information
|
||||
const survey = this.createImageSurvey(ImageSurvey.DEFAULT_SURVEY_ID);
|
||||
|
||||
const survey = ImageSurvey.fromLayerOptions(this, ImageLayer.DEFAULT_SURVEY);
|
||||
this.setBaseImageLayer(survey);
|
||||
} else {
|
||||
this.setBaseImageLayer(options.survey)
|
||||
}
|
||||
} else {
|
||||
} else if (options.surveyUrl) {
|
||||
// Add the image layers
|
||||
// For that we check the survey key of options
|
||||
// It can be given as a single string or an array of strings
|
||||
@@ -330,6 +300,9 @@ export let Aladin = (function () {
|
||||
}
|
||||
|
||||
this.setBaseImageLayer(url);
|
||||
} else {
|
||||
// This case should not happen because if there is no survey given
|
||||
// then the surveyUrl pointing to the DSS is given.
|
||||
}
|
||||
|
||||
this.view.showCatalog(options.showCatalog);
|
||||
@@ -374,13 +347,35 @@ export let Aladin = (function () {
|
||||
|
||||
// Status bar
|
||||
if (options.showStatusBar) {
|
||||
this.statusBar = new StatusBarBox(this);
|
||||
this.addUI(this.statusBar)
|
||||
let statusBarOptions = {};
|
||||
if (typeof options.showStatusBar === "object") {
|
||||
statusBarOptions = options.showStatusBar;
|
||||
}
|
||||
this.statusBar = new StatusBarBox(this, statusBarOptions);
|
||||
}
|
||||
|
||||
// Add the frame control
|
||||
if (options.showFrame) {
|
||||
this.addUI(new CooFrame(this))
|
||||
let cooFrame = CooFrameEnum.fromString(options.cooFrame, CooFrameEnum.J2000);
|
||||
let cooFrameControl = Input.select({
|
||||
name: 'frame',
|
||||
type: 'select',
|
||||
value: cooFrame.label,
|
||||
options: [CooFrameEnum.J2000.label, CooFrameEnum.J2000d.label, CooFrameEnum.GAL.label],
|
||||
change(e) {
|
||||
self.setFrame(e.target.value)
|
||||
},
|
||||
tooltip: {
|
||||
content: "Change the frame",
|
||||
position: {
|
||||
direction: 'bottom'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cooFrameControl.addClass('aladin-cooFrame');
|
||||
|
||||
this.addUI(cooFrameControl)
|
||||
}
|
||||
|
||||
// Add the location info
|
||||
@@ -397,28 +392,24 @@ export let Aladin = (function () {
|
||||
let stack = new OverlayStackButton(this);
|
||||
let simbad = new SimbadPointer(this);
|
||||
let grid = new GridEnabler(this);
|
||||
this.addUI(stack)
|
||||
this.addUI(simbad)
|
||||
this.addUI(grid)
|
||||
let settings = new SettingsButton(this, {features: {stack, simbad, grid}});
|
||||
|
||||
// Add the layers control
|
||||
if (!options.showLayersControl) {
|
||||
stack._hide();
|
||||
if (options.showLayersControl) {
|
||||
this.addUI(stack)
|
||||
}
|
||||
// Add the simbad pointer control
|
||||
if (!options.showSimbadPointerControl) {
|
||||
simbad._hide();
|
||||
if (options.showSimbadPointerControl) {
|
||||
this.addUI(simbad)
|
||||
}
|
||||
|
||||
// Add the projection control
|
||||
// Add the coo grid control
|
||||
if (!options.showCooGridControl) {
|
||||
grid._hide();
|
||||
if (options.showCooGridControl) {
|
||||
this.addUI(grid)
|
||||
}
|
||||
|
||||
// Settings control
|
||||
if (options.showSettingsControl) {
|
||||
let settings = new SettingsButton(this, {features: {stack, simbad, grid}});
|
||||
this.addUI(settings)
|
||||
}
|
||||
|
||||
@@ -435,11 +426,9 @@ export let Aladin = (function () {
|
||||
if (options.showFullscreenControl) {
|
||||
this.addUI(new FullScreenActionButton(self))
|
||||
}
|
||||
|
||||
this._applyMediaQueriesUI();
|
||||
}
|
||||
|
||||
Aladin.prototype._applyMediaQueriesUI = function() {
|
||||
/*Aladin.prototype._applyMediaQueriesUI = function() {
|
||||
const applyMediaQuery = function(maxWidth, matchingCallback, unmatchingCallback) {
|
||||
function mqFunction(x) {
|
||||
if (x.matches) { // If media query matches
|
||||
@@ -462,7 +451,6 @@ export let Aladin = (function () {
|
||||
|
||||
let self = this;
|
||||
|
||||
|
||||
applyMediaQuery('48rem', () => {
|
||||
if (self.projBtn) {
|
||||
self.projBtn.update({verbosity: 'reduced'})
|
||||
@@ -473,7 +461,7 @@ export let Aladin = (function () {
|
||||
self.projBtn.update({verbosity: 'full'})
|
||||
}
|
||||
})
|
||||
}
|
||||
}*/
|
||||
|
||||
/**** CONSTANTS ****/
|
||||
Aladin.VERSION = version;
|
||||
@@ -493,7 +481,7 @@ export let Aladin = (function () {
|
||||
fov: 60,
|
||||
backgroundColor: "rgb(60, 60, 60)",
|
||||
// Zoom toolbar
|
||||
showZoomControl: false,
|
||||
showZoomControl: true,
|
||||
// Menu toolbar
|
||||
showLayersControl: true,
|
||||
showFullscreenControl: true,
|
||||
@@ -640,18 +628,16 @@ export let Aladin = (function () {
|
||||
* Sets the field of view (FoV) of the Aladin instance to the specified angle in degrees.
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {number} FoV - The angle of the field of view in degrees.
|
||||
* @param {number} fovDegrees - The angle of the field of view in degrees.
|
||||
*
|
||||
* @example
|
||||
* let aladin = A.aladin('#aladin-lite-div');
|
||||
* aladin.setFoV(60);
|
||||
*/
|
||||
Aladin.prototype.setFoV = function (FoV) {
|
||||
this.view.setZoom(FoV);
|
||||
Aladin.prototype.setFoV = function (fovDegrees) {
|
||||
this.view.setZoom(fovDegrees);
|
||||
};
|
||||
|
||||
Aladin.prototype.setFov = Aladin.prototype.setFoV;
|
||||
|
||||
// @API
|
||||
// (experimental) try to adjust the FoV to the given object name. Does nothing if object is not known from Simbad
|
||||
Aladin.prototype.adjustFovForObject = function (objectName) {
|
||||
@@ -662,7 +648,7 @@ export let Aladin = (function () {
|
||||
};
|
||||
|
||||
|
||||
Aladin.prototype.getFovForObject = Aladin.prototype.getFoVForObject = function (objectName, callback) {
|
||||
Aladin.prototype.getFovForObject = function (objectName, callback) {
|
||||
var query = "SELECT galdim_majaxis, V FROM basic JOIN ident ON oid=ident.oidref JOIN allfluxes ON oid=allfluxes.oidref WHERE id='" + objectName + "'";
|
||||
var url = '//simbad.u-strasbg.fr/simbad/sim-tap/sync?query=' + encodeURIComponent(query) + '&request=doQuery&lang=adql&format=json&phase=run';
|
||||
|
||||
@@ -880,7 +866,7 @@ export let Aladin = (function () {
|
||||
}
|
||||
// planetary case
|
||||
else {
|
||||
const body = baseImageLayer.hipsBody;
|
||||
const body = baseImageLayer.properties.hipsBody;
|
||||
PlanetaryFeaturesNameResolver.resolve(targetName, body,
|
||||
function (data) { // success callback
|
||||
self.view.pointTo(data.lon, data.lat);
|
||||
@@ -1179,7 +1165,6 @@ export let Aladin = (function () {
|
||||
Aladin.prototype.addUI = function (ui) {
|
||||
this.ui.push(ui);
|
||||
ui.attachTo(this.aladinDiv)
|
||||
|
||||
// as the ui is pushed to the dom, setting position may need the aladin instance to work
|
||||
// so we recompute it
|
||||
if (ui.options) {
|
||||
@@ -1206,59 +1191,29 @@ export let Aladin = (function () {
|
||||
this.view.removeLayer(layer);
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Creates and return an image survey (HiPS) object
|
||||
* Please use {@link A.imageHiPS} instead for creating a new survey image
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} [name] - A convinient name for the survey, optional
|
||||
* @param {string} url - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>Or it can be a "CDS ID" that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* </ul>
|
||||
* @param {string} [cooFrame] - Values accepted: 'equatorial', 'icrs', 'icrsd', 'j2000', 'gal', 'galactic'
|
||||
* @param {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
* @param {ImageSurveyOptions} [options] - Options describing the survey
|
||||
* @returns {ImageSurvey} A HiPS image object.
|
||||
*/
|
||||
Aladin.prototype.createImageSurvey = function(id, name, url, cooFrame, maxOrder, options) {
|
||||
let surveyOptions = ImageSurvey.cache[id];
|
||||
// @oldAPI
|
||||
Aladin.prototype.createImageSurvey = function(id, name, rootUrl, cooFrame, maxOrder, options = {}) {
|
||||
let cfg = this.cacheSurveys.get(id);
|
||||
if (!cfg) {
|
||||
// Add the cooFrame and maxOrder given by the user
|
||||
// to the list of options passed to the ImageSurvey constructor
|
||||
if (cooFrame) {
|
||||
options.cooFrame = cooFrame;
|
||||
}
|
||||
|
||||
if (!surveyOptions) {
|
||||
surveyOptions = {url, name, maxOrder, cooFrame, ...options};
|
||||
ImageSurvey.cache[id] = surveyOptions;
|
||||
if (maxOrder) {
|
||||
options.maxOrder = maxOrder;
|
||||
}
|
||||
|
||||
cfg = {id, name, rootUrl, options};
|
||||
this.cacheSurveys.set(id, cfg);
|
||||
} else {
|
||||
cfg = Utils.clone(cfg)
|
||||
}
|
||||
|
||||
return new ImageSurvey(id, surveyOptions.url, surveyOptions);
|
||||
return new ImageSurvey(cfg.id, cfg.name, cfg.rootUrl, cfg.options, this.view);
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Creates and return an image survey (HiPS) object.
|
||||
* Please use {@link A.imageHiPS} instead for creating a new survey image
|
||||
*
|
||||
* @function createImageSurvey
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} [name] - A convinient name for the survey, optional
|
||||
* @param {string} url - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>Or it can be a "CDS ID" that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* </ul>
|
||||
* @param {string} [cooFrame] - Values accepted: 'equatorial', 'icrs', 'icrsd', 'j2000', 'gal', 'galactic'
|
||||
* @param {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
* @param {ImageSurveyOptions} [options] - Options describing the survey
|
||||
* @returns {ImageSurvey} A HiPS image object.
|
||||
*/
|
||||
Aladin.createImageSurvey = Aladin.prototype.createImageSurvey;
|
||||
|
||||
|
||||
Aladin.prototype.createImageFITS = function(url, name, options, successCallback, errorCallback) {
|
||||
Aladin.prototype.createImageFITS = function(url, name, options = {}, successCallback = undefined, errorCallback = undefined) {
|
||||
try {
|
||||
url = new URL(url);
|
||||
} catch(e) {
|
||||
@@ -1270,103 +1225,39 @@ export let Aladin = (function () {
|
||||
// Do not use proxy with CORS headers until we solve that: https://github.com/MattiasBuelens/wasm-streams/issues/20
|
||||
//url = Utils.handleCORSNotSameOrigin(url);
|
||||
|
||||
let image = ImageFITS.cache[url];
|
||||
if (!image) {
|
||||
image = new ImageFITS(url, name, options, successCallback, errorCallback)
|
||||
ImageFITS.cache[url] = image;
|
||||
let cfg = this.cacheSurveys.get(url);
|
||||
if (!cfg) {
|
||||
cfg = {url, name, options, successCallback, errorCallback}
|
||||
this.cacheSurveys.set(url, cfg);
|
||||
} else {
|
||||
cfg = Utils.clone(cfg)
|
||||
}
|
||||
|
||||
return image;
|
||||
return new ImageFITS(cfg.url, cfg.name, this.view, cfg.options, cfg.successCallback, cfg.errorCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a FITS image object
|
||||
*
|
||||
* @function createImageFITS
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
* @param {string} url - The url of the fits.
|
||||
* @param {string} [name] - The url of the fits.
|
||||
* @param {ImageSurveyOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
* @param {function} [error] - A success callback
|
||||
* @returns {ImageSurvey} A FITS image object.
|
||||
*/
|
||||
Aladin.createImageFITS = Aladin.prototype.createImageFITS;
|
||||
Aladin.prototype.newImageSurvey = function(rootUrlOrId, options) {
|
||||
const idOrUrl = rootUrlOrId;
|
||||
// Check if the survey has already been added
|
||||
// Create a new ImageSurvey
|
||||
const name = idOrUrl;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Create a new layer from an url or CDS ID.
|
||||
* Please use {@link A.imageHiPS} instead for creating a new survey image
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
* @param {string} url - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>Or it can be a "CDS ID" that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* </ul>
|
||||
* @param {ImageSurveyOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
* @param {function} [error] - A success callback
|
||||
* @returns {ImageSurvey} A FITS image object.
|
||||
*/
|
||||
Aladin.prototype.newImageSurvey = function(url, options) {
|
||||
const id = url;
|
||||
return A.imageHiPS(id, url, options);
|
||||
return this.createImageSurvey(idOrUrl, name, idOrUrl, null, null, options);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new HiPS layer to the view on top of the others
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey} [survey="CDS/P/DSS2/color"] - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. It can also be an {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* </ul>
|
||||
* By default, the {@link https://alasky.cds.unistra.fr/DSS/DSSColor/|Digital Sky Survey 2} survey will be displayed
|
||||
*/
|
||||
Aladin.prototype.addNewImageLayer = function(survey="CDS/P/DSS2/color") {
|
||||
Aladin.prototype.addNewImageLayer = function() {
|
||||
let layerName = Utils.uuidv4();
|
||||
this.setOverlayImageLayer(survey, layerName);
|
||||
// A HIPS_LAYER_ADDED will be called after the hips is added to the view
|
||||
this.setOverlayImageLayer('CDS/P/DSS2/color', layerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the base layer of the view
|
||||
*
|
||||
* It internally calls {@link Aladin#setBaseImageLayer|Aladin.setBaseImageLayer} with the url/{@link ImageSurvey}/{@link ImageFITS} given
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS identifier that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
// @param imageSurvey : ImageSurvey object or image survey identifier
|
||||
// @api
|
||||
// @old
|
||||
Aladin.prototype.setImageLayer = function(imageLayer) {
|
||||
this.setBaseImageLayer(imageLayer);
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the base layer of the view
|
||||
*
|
||||
* It internally calls {@link Aladin#setBaseImageLayer|Aladin.setBaseImageLayer} with the url/{@link ImageSurvey}/{@link ImageFITS} given
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
Aladin.prototype.setImageSurvey = Aladin.prototype.setImageLayer;
|
||||
|
||||
// @param imageSurvey : ImageSurvey object or image survey identifier
|
||||
@@ -1393,20 +1284,9 @@ export let Aladin = (function () {
|
||||
this.view.removeImageLayer(layer);
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the base layer of the view
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
Aladin.prototype.setBaseImageLayer = function(urlOrHiPSOrFITS) {
|
||||
return this.setOverlayImageLayer(urlOrHiPSOrFITS, "base");
|
||||
|
||||
Aladin.prototype.setBaseImageLayer = function(idOrSurvey) {
|
||||
return this.setOverlayImageLayer(idOrSurvey, "base");
|
||||
};
|
||||
|
||||
// @api
|
||||
@@ -1414,31 +1294,35 @@ export let Aladin = (function () {
|
||||
return this.view.getImageLayer("base");
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a new HiPS/FITS image layer in the view
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
* @param {string} [layer="overlay"] - A layer name. By default 'overlay' is chosen and it is destined to be plot
|
||||
* on top the 'base' layer. If the layer is already present in the view, it will be replaced by the new HiPS/FITS image given here.
|
||||
*/
|
||||
Aladin.prototype.setOverlayImageLayer = function (urlOrHiPSOrFITS, layer = "overlay") {
|
||||
// @api
|
||||
Aladin.prototype.setOverlayImageLayer = function (idOrUrlOrImageLayer, layer = "overlay") {
|
||||
let imageLayer;
|
||||
// 1. User gives an ID
|
||||
if (typeof urlOrHiPSOrFITS === "string") {
|
||||
const idOrUrl = urlOrHiPSOrFITS;
|
||||
|
||||
imageLayer = A.imageHiPS(idOrUrl, idOrUrl);
|
||||
if (typeof idOrUrlOrImageLayer === "string") {
|
||||
const idOrUrl = idOrUrlOrImageLayer;
|
||||
// Check if the survey has already been added
|
||||
// Create a new ImageSurvey
|
||||
/*let isUrl = false;
|
||||
if (idOrUrl.includes("http")) {
|
||||
isUrl = true;
|
||||
}
|
||||
const name = idOrUrl;
|
||||
|
||||
if (isUrl) {
|
||||
const url = idOrUrl;
|
||||
const id = url;
|
||||
// Url
|
||||
imageLayer = this.createImageSurvey(idOrUrl, name, idOrUrl, null, null);
|
||||
} else {
|
||||
const id = idOrUrl;
|
||||
// ID
|
||||
imageLayer = this.createImageSurvey(idOrUrl, name, idOrUrl, null, null);
|
||||
}*/
|
||||
const name = idOrUrl;
|
||||
imageLayer = this.createImageSurvey(idOrUrl, name, idOrUrl, null, null);
|
||||
// 2. User gives a non resolved promise
|
||||
} else {
|
||||
imageLayer = urlOrHiPSOrFITS;
|
||||
imageLayer = idOrUrlOrImageLayer;
|
||||
}
|
||||
|
||||
return this.view.setOverlayImageLayer(imageLayer, layer);
|
||||
@@ -1557,12 +1441,8 @@ export let Aladin = (function () {
|
||||
* Enters selection mode
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string} [mode='rect'] - The mode of selection, can be either, 'rect', 'poly', or 'circle'
|
||||
* @param {function} [callback] - A function called once the selection has been done
|
||||
* The callback accepts one parameter depending of the mode used: <br/>
|
||||
* - If mode='circle' that parameter is of type {@link CircleSelection} <br/>
|
||||
* - If mode='rect' that parameter is of type {@link RectSelection} <br/>
|
||||
* - If mode='poly' that parameter is of type {@link PolygonSelection}
|
||||
* @param {string} mode=rect - The mode of selection, can be either, 'rect', 'poly', or 'circle'
|
||||
* @param {function} callback - A function called once the selection has been done
|
||||
*
|
||||
* @example
|
||||
* // Creates and add a MOC from the user polygonal selection
|
||||
@@ -1589,6 +1469,11 @@ export let Aladin = (function () {
|
||||
Aladin.prototype.select = async function (mode = 'rect', callback) {
|
||||
await this.reticle.loaded;
|
||||
|
||||
// Default callback selects objects
|
||||
callback = callback || ((selection) => {
|
||||
this.view.selectObjects(selection);
|
||||
});
|
||||
|
||||
this.fire('selectstart', {mode, callback});
|
||||
};
|
||||
|
||||
@@ -1625,6 +1510,7 @@ export let Aladin = (function () {
|
||||
* This method allows you to customize the appearance of the coordinate grid in the Aladin Lite view.
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @param {Object} options - Options to customize the coordinate grid.
|
||||
* @param {string} [options.color] - The color of the coordinate grid.
|
||||
* @param {number} [options.opacity] - The opacity of the coordinate grid (value between 0 and 1).
|
||||
@@ -1762,7 +1648,7 @@ export let Aladin = (function () {
|
||||
let radecsys;
|
||||
|
||||
if (this.getBaseImageLayer().isPlanetaryBody()) {
|
||||
const body = this.getBaseImageLayer().hipsBody
|
||||
const body = this.getBaseImageLayer().properties.hipsBody
|
||||
if (body in solarSystemObjects) {
|
||||
cooType1 = `${solarSystemObjects[body]}LN-`;
|
||||
cooType2 = `${solarSystemObjects[body]}LT-`;
|
||||
@@ -1806,65 +1692,39 @@ export let Aladin = (function () {
|
||||
return WCS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restrict the FoV range between a min and a max value
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {number} minFoV - in degrees when zoom in at max. If undefined, the zooming in is not limited
|
||||
* @param {number} maxFoV - in degrees when zoom out at max. If undefined, the zooming out is not limited
|
||||
*
|
||||
* @example
|
||||
* let aladin = A.aladin('#aladin-lite-div');
|
||||
* aladin.setFoVRange(30, 60);
|
||||
*/
|
||||
Aladin.prototype.setFoVRange = function (minFoV, maxFoV) {
|
||||
if (minFoV > maxFoV) {
|
||||
var tmp = minFoV;
|
||||
minFoV = maxFoV;
|
||||
maxFoV = tmp;
|
||||
/** restrict FOV range
|
||||
* @API
|
||||
* @param minFOV in degrees when zoom in at max
|
||||
* @param maxFOV in degrees when zoom out at max
|
||||
*/
|
||||
Aladin.prototype.setFovRange = Aladin.prototype.setFOVRange = function (minFOV, maxFOV) {
|
||||
if (minFOV > maxFOV) {
|
||||
var tmp = minFOV;
|
||||
minFOV = maxFOV;
|
||||
maxFOV = tmp;
|
||||
}
|
||||
|
||||
this.view.minFoV = minFoV;
|
||||
this.view.maxFoV = maxFoV;
|
||||
this.view.minFOV = minFOV;
|
||||
this.view.maxFOV = maxFOV;
|
||||
|
||||
// reset the field of view
|
||||
this.setFoV(this.view.fov)
|
||||
};
|
||||
|
||||
Aladin.prototype.setFOVRange = Aladin.prototype.setFoVRange;
|
||||
|
||||
/**
|
||||
* Transform pixel coordinates to world coordinates.
|
||||
*
|
||||
* The origin (0,0) of pixel coordinates is at the top-left corner of the Aladin Lite view.
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @param {number} x - The x-coordinate in pixel coordinates.
|
||||
* @param {number} y - The y-coordinate in pixel coordinates.
|
||||
* @param {CooFrame} [frame] - The frame in which we want to retrieve the coordinates.
|
||||
* If not given, the frame chosen is the one from the view
|
||||
*
|
||||
* @returns {number[]} - An array representing the [Right Ascension, Declination] coordinates in degrees in the `frame`.
|
||||
* If not specified, returns the coo in the frame of the current view.
|
||||
* @returns {number[]} - An array representing the [Right Ascension, Declination] coordinates in degrees.
|
||||
*
|
||||
* @throws {Error} Throws an error if an issue occurs during the transformation.
|
||||
*/
|
||||
Aladin.prototype.pix2world = function (x, y, frame) {
|
||||
let radec = this.view.wasm.screenToWorld(x, y);
|
||||
|
||||
frame = frame || this.view.cooFrame.label;
|
||||
frame = CooFrameEnum.fromString(frame, CooFrameEnum.J2000);
|
||||
|
||||
if (frame !== this.view.cooFrame) {
|
||||
if (frame.label === 'Galactic') {
|
||||
console.warn('Conversion from icrs to galactic not yet impl')
|
||||
} else {
|
||||
radec = this.view.wasm.viewToICRSCooSys(radec[0], radec[1]);
|
||||
}
|
||||
}
|
||||
|
||||
let [ra, dec] = radec;
|
||||
Aladin.prototype.pix2world = function (x, y) {
|
||||
const [ra, dec] = this.view.wasm.screenToWorld(x, y);
|
||||
|
||||
if (ra < 0) {
|
||||
return [ra + 360.0, dec];
|
||||
@@ -1877,8 +1737,9 @@ export let Aladin = (function () {
|
||||
* Transform world coordinates to pixel coordinates in the view.
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {number} ra - The Right Ascension (RA) coordinate in degrees. Frame considered is the current view frame
|
||||
* @param {number} dec - The Declination (Dec) coordinate in degrees. Frame considered is the current view frame
|
||||
*
|
||||
* @param {number} ra - The Right Ascension (RA) coordinate in degrees.
|
||||
* @param {number} dec - The Declination (Dec) coordinate in degrees.
|
||||
*
|
||||
* @returns {number[]} - An array representing the [x, y] coordinates in pixel coordinates in the view.
|
||||
*
|
||||
@@ -1892,20 +1753,19 @@ export let Aladin = (function () {
|
||||
* Get the angular distance in degrees between two locations
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @param {number} x1 - The x-coordinate of the first pixel coordinates.
|
||||
* @param {number} y1 - The y-coordinate of the first pixel coordinates.
|
||||
* @param {number} x2 - The x-coordinate of the second pixel coordinates.
|
||||
* @param {number} y2 - The y-coordinate of the second pixel coordinates.
|
||||
* @param {CooFrame} [frame] - The frame in which we want to retrieve the coordinates.
|
||||
* If not given, the frame chosen is the one from the view
|
||||
*
|
||||
* @returns {number} - The angular distance between the two pixel coordinates in degrees
|
||||
*
|
||||
* @throws {Error} Throws an error if an issue occurs during the transformation.
|
||||
*/
|
||||
Aladin.prototype.angularDist = function (x1, y1, x2, y2, frame) {
|
||||
const [ra1, dec1] = this.pix2world(x1, y1, frame);
|
||||
const [ra2, dec2] = this.pix2world(x2, y2, frame);
|
||||
Aladin.prototype.angularDist = function (x1, y1, x2, y2) {
|
||||
const [ra1, dec1] = this.pix2world(x1, y1);
|
||||
const [ra2, dec2] = this.pix2world(x2, y2);
|
||||
|
||||
return this.wasm.angularDist(ra1, dec1, ra2, dec2);
|
||||
};
|
||||
@@ -1914,6 +1774,7 @@ export let Aladin = (function () {
|
||||
* Gets a set of points along the current Field of View (FoV) corners.
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @param {number} nbSteps - The number of points to return along each side (the total number of points returned is 4 * nbSteps).
|
||||
*
|
||||
* @returns {number[][]} - A set of positions along the current FoV with the following format: [[ra1, dec1], [ra2, dec2], ..., [ra_n, dec_n]].
|
||||
@@ -1922,7 +1783,7 @@ export let Aladin = (function () {
|
||||
* @throws {Error} Throws an error if an issue occurs during the transformation.
|
||||
*
|
||||
*/
|
||||
Aladin.prototype.getFoVCorners = function (nbSteps) {
|
||||
Aladin.prototype.getFovCorners = function (nbSteps) {
|
||||
// default value: 1
|
||||
if (!nbSteps || nbSteps < 1) {
|
||||
nbSteps = 1;
|
||||
@@ -1950,6 +1811,7 @@ export let Aladin = (function () {
|
||||
* Gets the current Field of View (FoV) size in degrees as a 2-element array.
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @returns {number[]} - A 2-element array representing the current FoV size in degrees. The first element is the FoV width,
|
||||
* and the second element is the FoV height.
|
||||
*/
|
||||
@@ -1968,12 +1830,11 @@ export let Aladin = (function () {
|
||||
return [fovX, fovY];
|
||||
};
|
||||
|
||||
Aladin.prototype.getFoV = Aladin.prototype.getFov;
|
||||
|
||||
/**
|
||||
* Returns the size in pixels for the Aladin view
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @returns {number[]} - A 2-element array representing the current Aladin view size in pixels. The first element is the width,
|
||||
* and the second element is the height.
|
||||
*/
|
||||
@@ -1982,10 +1843,9 @@ export let Aladin = (function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the HTML div element
|
||||
* @API
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @return {HTMLElement} - The aladin lite div HTML element
|
||||
* @return the jQuery object representing the DIV element where the Aladin Lite instance lies
|
||||
*/
|
||||
Aladin.prototype.getParentDiv = function () {
|
||||
return this.aladinDiv;
|
||||
@@ -2084,6 +1944,7 @@ export let Aladin = (function () {
|
||||
* Display a JPEG image in the Aladin Lite view.
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @param {string} url - The URL of the JPEG image.
|
||||
* @param {Object} options - Options to customize the display. Can include the following properties:
|
||||
* @param {string} options.label - A label for the displayed image.
|
||||
@@ -2093,8 +1954,7 @@ export let Aladin = (function () {
|
||||
* @param {Function} successCallback - The callback function to be executed on a successful display.
|
||||
* The callback gives the ra, dec, and fov of the image;
|
||||
* @param {Function} errorCallback - The callback function to be executed if an error occurs during display.
|
||||
* @param {string} [layer="base"] - The name of the layer. If not specified, it will be replace the base layer.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* aladin.displayJPG(
|
||||
* // the JPG to transform to HiPS
|
||||
@@ -2127,6 +1987,7 @@ export let Aladin = (function () {
|
||||
* Display a JPEG image in the Aladin Lite view.
|
||||
*
|
||||
* @memberof Aladin
|
||||
*
|
||||
* @param {string} url - The URL of the JPEG image.
|
||||
* @param {Object} options - Options to customize the display. Can include the following properties:
|
||||
* @param {string} options.label - A label for the displayed image.
|
||||
@@ -2136,7 +1997,6 @@ export let Aladin = (function () {
|
||||
* @param {Function} successCallback - The callback function to be executed on a successful display.
|
||||
* The callback gives the ra, dec, and fov of the image;
|
||||
* @param {Function} errorCallback - The callback function to be executed if an error occurs during display.
|
||||
* @param {string} [layer="overlay"] - The name of the layer. If not specified, it will add a new overlay layer on top of the base.
|
||||
*
|
||||
* @example
|
||||
* aladin.displayJPG(
|
||||
@@ -2151,7 +2011,7 @@ export let Aladin = (function () {
|
||||
* })
|
||||
*);
|
||||
*/
|
||||
Aladin.prototype.displayJPG = function (url, options, successCallback, errorCallback, layer = "overlay") {
|
||||
Aladin.prototype.displayJPG = Aladin.prototype.displayPNG = function (url, options, successCallback, errorCallback) {
|
||||
options = options || {};
|
||||
options.color = true;
|
||||
options.label = options.label || "JPG/PNG image";
|
||||
@@ -2201,7 +2061,7 @@ export let Aladin = (function () {
|
||||
var meta = response.data.meta;
|
||||
|
||||
const survey = self.createImageSurvey(response.data.url, label, response.data.url);
|
||||
self.setOverlayImageLayer(survey, layer);
|
||||
self.setOverlayImageLayer(survey, "overlay");
|
||||
|
||||
var transparency = (options && options.transparency) || 1.0;
|
||||
survey.setOpacity(transparency);
|
||||
@@ -2223,8 +2083,6 @@ export let Aladin = (function () {
|
||||
});
|
||||
};
|
||||
|
||||
Aladin.prototype.displayPNG = Aladin.prototype.displayJPG;
|
||||
|
||||
/*
|
||||
Aladin.prototype.setReduceDeformations = function (reduce) {
|
||||
this.reduceDeformations = reduce;
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
* Author: Thomas Boch[CDS]
|
||||
*
|
||||
*****************************************************************************/
|
||||
import { HPXVertices } from "../core/pkg/core";
|
||||
import A from "./A";
|
||||
import { Aladin } from "./Aladin";
|
||||
|
||||
/**
|
||||
@@ -146,12 +148,8 @@ export let AladinUtils = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* Converts celestial coordinates (ra, dec) to screen coordinates (x, y) in pixels within the view.
|
||||
* Use {@link Aladin.world2pix} instead
|
||||
*
|
||||
*
|
||||
*
|
||||
* @function
|
||||
* @memberof AladinUtils
|
||||
* @name radecToViewXy
|
||||
@@ -162,7 +160,25 @@ export let AladinUtils = {
|
||||
* @returns {number[]} xy - A 2 elements array representing the screen coordinates [X, Y] in pixels.
|
||||
*/
|
||||
radecToViewXy: function(ra, dec, aladin) {
|
||||
return aladin.world2pix(ra, dec);
|
||||
let xy = aladin.view.wasm.worldToScreen(ra, dec);
|
||||
return xy;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts screen coordinates (X, Y) to clip coordinates within the view (coordinates lying between 0 and 1).
|
||||
*
|
||||
* @function
|
||||
* @memberof AladinUtils
|
||||
* @name viewXyToClipXy
|
||||
*
|
||||
* @param {number} x - X-coordinate in pixel screen coordinates
|
||||
* @param {number} y - Y-coordinate in pixel screen coordinates.
|
||||
* @param {Aladin} aladin - Aladin Lite object containing the WebAssembly API.
|
||||
* @returns {number[]} xy - An array representing the coordinates [X, Y] in clipping space.
|
||||
*/
|
||||
viewXyToClipXy: function(x, y, aladin) {
|
||||
let xy = aladin.view.wasm.screenToClip(x, y);
|
||||
return xy;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,6 +55,7 @@ export let Catalog = (function() {
|
||||
* @param {string} [options.name="catalog"] - The name of the catalog.
|
||||
* @param {string} [options.color] - The color associated with the catalog.
|
||||
* @param {number} [options.sourceSize=8] - The size of the sources in the catalog.
|
||||
* @param {number} [options.markerSize=12] - The size of the markers associated with sources.
|
||||
* @param {string} [options.shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
|
||||
* @param {number} [options.limit] - The maximum number of sources to display.
|
||||
* @param {function} [options.onClick] - The callback function to execute on a source click.
|
||||
@@ -62,10 +63,7 @@ export let Catalog = (function() {
|
||||
* @param {string} [options.raField] - The ID or name of the field holding Right Ascension (RA).
|
||||
* @param {string} [options.decField] - The ID or name of the field holding Declination (dec).
|
||||
* @param {function} [options.filter] - The filtering function for sources.
|
||||
* @param {string} [options.selectionColor] - The color to apply to selected sources in the catalog.
|
||||
* @param {string} [options.hoverColor] - The color to apply to sources in the catalog when they are hovered.
|
||||
* @param {boolean} [options.displayLabel=false] - Whether to display labels for sources.
|
||||
* @param {string} [options.labelColumn] - The name of the column to be used for the label.
|
||||
* @param {string} [options.labelColor] - The color of the source labels.
|
||||
* @param {string} [options.labelFont="10px sans-serif"] - The font for the source labels.
|
||||
*
|
||||
@@ -83,8 +81,6 @@ export let Catalog = (function() {
|
||||
* raField: "ra",
|
||||
* decField: "dec",
|
||||
* filter: (source) => source.mag < 15,
|
||||
* selectionColor: "#00ff00",
|
||||
* hoverColor: "#ff00ff",
|
||||
* displayLabel: true,
|
||||
* labelColor: "#00ff00",
|
||||
* labelFont: "12px Arial"
|
||||
@@ -111,8 +107,7 @@ export let Catalog = (function() {
|
||||
|
||||
// allows for filtering of sources
|
||||
this.filterFn = options.filter || undefined; // TODO: do the same for catalog
|
||||
this.selectionColor = options.selectionColor || '#00ff00';
|
||||
this.hoverColor = options.hoverColor || this.color;
|
||||
|
||||
this.displayLabel = options.displayLabel || false;
|
||||
this.labelColor = options.labelColor || this.color;
|
||||
this.labelFont = options.labelFont || '10px sans-serif';
|
||||
@@ -123,6 +118,8 @@ export let Catalog = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
this.selectionColor = '#00ff00';
|
||||
|
||||
this.showFieldCallback = {}; // callbacks when the user clicks on a cell in the measurement table associated
|
||||
this.fields = undefined;
|
||||
this.uuid = Utils.uuidv4();
|
||||
@@ -465,7 +462,7 @@ export let Catalog = (function() {
|
||||
|
||||
this.cacheCanvas = Catalog.createShape(this.shape, this.color, this.sourceSize);
|
||||
this.cacheSelectCanvas = Catalog.createShape(this.shape, this.selectionColor, this.selectSize);
|
||||
this.cacheHoverCanvas = Catalog.createShape(this.shape, this.hoverColor, this.selectSize);
|
||||
this.cacheHoverCanvas = Catalog.createShape(this.shape, this.hoverColor, this.sourceSize);
|
||||
|
||||
this.reportChange();
|
||||
};
|
||||
@@ -510,7 +507,6 @@ export let Catalog = (function() {
|
||||
footprintsToAdd[k].setCatalog(this);
|
||||
footprintsToAdd[k].setColor(this.color);
|
||||
footprintsToAdd[k].setSelectionColor(this.selectionColor);
|
||||
footprintsToAdd[k].setHoverColor(this.hoverColor);
|
||||
}
|
||||
this.reportChange();
|
||||
};
|
||||
@@ -736,9 +732,6 @@ export let Catalog = (function() {
|
||||
else if (s.marker && s.useMarkerDefaultIcon) {
|
||||
ctx.drawImage(this.cacheMarkerCanvas, s.x-this.sourceSize/2, s.y-this.sourceSize/2);
|
||||
}
|
||||
else if (s.isHovered) {
|
||||
ctx.drawImage(this.cacheHoverCanvas, s.x-this.selectSize/2, s.y-this.selectSize/2);
|
||||
}
|
||||
else if (s.isSelected) {
|
||||
ctx.drawImage(this.cacheSelectCanvas, s.x-this.selectSize/2, s.y-this.selectSize/2);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,6 @@ export let Circle = (function() {
|
||||
this.color = options['color'] || undefined;
|
||||
this.fillColor = options['fillColor'] || undefined;
|
||||
this.lineWidth = options["lineWidth"] || 2;
|
||||
this.selectionColor = options["selectionColor"] || '#00ff00';
|
||||
this.hoverColor = options["hoverColor"] || undefined;
|
||||
|
||||
// TODO : all graphic overlays should have an id
|
||||
this.id = 'circle-' + Utils.uuidv4();
|
||||
@@ -53,7 +51,7 @@ export let Circle = (function() {
|
||||
|
||||
this.isShowing = true;
|
||||
this.isSelected = false;
|
||||
this.isHovered = false;
|
||||
this.selectionColor = '#00ff00';
|
||||
};
|
||||
|
||||
Circle.prototype.setColor = function(color) {
|
||||
@@ -76,16 +74,6 @@ export let Circle = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
Circle.prototype.setHoverColor = function(color) {
|
||||
if (this.hoverColor == color) {
|
||||
return;
|
||||
}
|
||||
this.hoverColor = color;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
};
|
||||
|
||||
Circle.prototype.setLineWidth = function(lineWidth) {
|
||||
if (this.lineWidth == lineWidth) {
|
||||
return;
|
||||
@@ -144,26 +132,6 @@ export let Circle = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
Circle.prototype.hover = function() {
|
||||
if (this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = true;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
Circle.prototype.unhover = function() {
|
||||
if (! this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = false;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
Circle.prototype.isFootprint = function() {
|
||||
return true;
|
||||
}
|
||||
@@ -256,9 +224,8 @@ export let Circle = (function() {
|
||||
} else {
|
||||
ctx.strokeStyle = Overlay.increaseBrightness(baseColor, 50);
|
||||
}
|
||||
} else if (this.isHovered) {
|
||||
ctx.strokeStyle = this.hoverColor || Overlay.increaseBrightness(baseColor, 25);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ctx.strokeStyle = baseColor;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,31 +222,7 @@
|
||||
return [this.minCut, this.maxCut];
|
||||
};
|
||||
|
||||
ColorCfg.COLORMAPS = [
|
||||
"blues",
|
||||
"cividis",
|
||||
"cubehelix",
|
||||
"eosb",
|
||||
"grayscale",
|
||||
"inferno",
|
||||
"magma",
|
||||
"native",
|
||||
"parula",
|
||||
"plasma",
|
||||
"rainbow",
|
||||
"rdbu",
|
||||
"rdylbu",
|
||||
"redtemperature",
|
||||
"sinebow",
|
||||
"spectral",
|
||||
"summer",
|
||||
"viridis",
|
||||
"ylgnbu",
|
||||
"ylorbr",
|
||||
"red",
|
||||
"green",
|
||||
"blue"
|
||||
];
|
||||
ColorCfg.COLORMAPS = [];
|
||||
|
||||
return ColorCfg;
|
||||
})();
|
||||
|
||||
275
src/js/ColorMap.js
Normal file
275
src/js/ColorMap.js
Normal file
@@ -0,0 +1,275 @@
|
||||
// Copyright 2013 - UDS/CNRS
|
||||
// The Aladin Lite program is distributed under the terms
|
||||
// of the GNU General Public License version 3.
|
||||
//
|
||||
// This file is part of Aladin Lite.
|
||||
//
|
||||
// Aladin Lite is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3 of the License.
|
||||
//
|
||||
// Aladin Lite is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// The GNU General Public License is available in COPYING file
|
||||
// along with Aladin Lite.
|
||||
//
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File ColorMap.js
|
||||
*
|
||||
* Author: Thomas Boch[CDS]
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
import { AladinUtils } from "./AladinUtils.js";
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.0
|
||||
*/
|
||||
export let ColorMap = (function() {
|
||||
|
||||
|
||||
// constructor
|
||||
let ColorMap = function(view) {
|
||||
this.view = view;
|
||||
this.reversed = false;
|
||||
this.mapName = 'native';
|
||||
this.sig = this.signature();
|
||||
};
|
||||
|
||||
ColorMap.MAPS = {};
|
||||
|
||||
ColorMap.MAPS['eosb'] = {
|
||||
name: 'Eos B',
|
||||
r: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,9,18,27,36,45,49,57,72,81,91,100,109,118,127,
|
||||
136,131,139,163,173,182,191,200,209,218,227,213,221,255,255,255,255,255,
|
||||
255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,255,255,
|
||||
255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,229,255,
|
||||
255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,
|
||||
229,255,255,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,
|
||||
255,229,229,255,255,255,255,255,255,255,255,229,229,255,253,251,249,247,
|
||||
245,243,241,215,214,235,234,232,230,228,226,224,222,198,196,216,215,213,
|
||||
211,209,207,205,203,181,179,197,196,194,192,190,188,186,184,164,162,178,
|
||||
176,175,173,171,169,167,165,147,145,159,157,156,154,152,150,148,146,130,
|
||||
128,140,138,137,135,133,131,129,127,113,111,121,119,117,117],
|
||||
g: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,15,23,31,39,47,55,57,64,79,87,95,
|
||||
103,111,119,127,135,129,136,159,167,175,183,191,199,207,215,200,207,239,
|
||||
247,255,255,255,255,255,255,229,229,255,255,255,255,255,255,255,255,229,
|
||||
229,255,255,255,255,255,255,255,255,229,229,255,250,246,242,238,233,229,
|
||||
225,198,195,212,208,204,199,195,191,187,182,160,156,169,165,161,157,153,
|
||||
148,144,140,122,118,127,125,123,121,119,116,114,112,99,97,106,104,102,
|
||||
99,97,95,93,91,80,78,84,82,80,78,76,74,72,70,61,59,63,61,59,57,55,53,50,
|
||||
48,42,40,42,40,38,36,33,31,29,27,22,21,21,19,16,14,12,13,8,6,3,1,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
||||
b: [116,121,127,131,136,140,144,148,153,
|
||||
157,145,149,170,174,178,182,187,191,195,199,183,187,212,216,221,225,229,
|
||||
233,238,242,221,225,255,247,239,231,223,215,207,199,172,164,175,167,159,
|
||||
151,143,135,127,119,100,93,95,87,79,71,63,55,47,39,28,21,15,7,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0]
|
||||
};
|
||||
ColorMap.MAPS['rainbow'] = {
|
||||
name: 'Rainbow',
|
||||
r: [0,4,9,13,18,22,27,31,36,40,45,50,54,
|
||||
58,61,64,68,69,72,74,77,79,80,82,83,85,84,86,87,88,86,87,87,87,85,84,84,
|
||||
84,83,79,78,77,76,71,70,68,66,60,58,55,53,46,43,40,36,33,25,21,16,12,4,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,12,21,25,29,33,42,
|
||||
46,51,55,63,67,72,76,80,89,93,97,101,110,114,119,123,131,135,140,144,153,
|
||||
157,161,165,169,178,182,187,191,199,203,208,212,221,225,229,233,242,246,
|
||||
250,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255],
|
||||
g: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,4,8,16,21,25,29,38,42,46,51,55,63,67,72,76,84,89,93,97,
|
||||
106,110,114,119,127,131,135,140,144,152,157,161,165,174,178,182,187,195,
|
||||
199,203,208,216,220,225,229,233,242,246,250,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,250,242,238,233,229,221,216,212,208,199,195,191,187,178,174,170,165,
|
||||
161,153,148,144,140,131,127,123,119,110,106,102,97,89,85,80,76,72,63,59,
|
||||
55,51,42,38,34,29,21,17,12,8,0],
|
||||
b: [0,3,7,10,14,19,23,28,32,38,43,48,53,
|
||||
59,63,68,72,77,81,86,91,95,100,104,109,113,118,122,127,132,136,141,145,
|
||||
150,154,159,163,168,173,177,182,186,191,195,200,204,209,214,218,223,227,
|
||||
232,236,241,245,250,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,246,242,238,233,225,220,216,212,203,199,195,191,
|
||||
187,178,174,170,165,157,152,148,144,135,131,127,123,114,110,106,102,97,
|
||||
89,84,80,76,67,63,59,55,46,42,38,34,25,21,16,12,8,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
};
|
||||
ColorMap.MAPS['cubehelix'] = {
|
||||
name: 'Cubehelix',
|
||||
r: [0,1,3,4,6,8,9,10,12,13,14,15,17,18,
|
||||
19,20,20,21,22,23,23,24,24,25,25,25,26,26,26,26,26,26,26,26,26,26,26,25,
|
||||
25,25,25,24,24,24,23,23,23,23,22,22,22,21,21,21,21,21,21,20,20,20,21,21,
|
||||
21,21,21,22,22,22,23,23,24,25,26,27,27,28,30,31,32,33,35,36,38,39,41,43,
|
||||
45,47,49,51,53,55,57,60,62,65,67,70,72,75,78,81,83,86,89,92,95,98,101,104,
|
||||
107,110,113,116,120,123,126,129,132,135,138,141,144,147,150,153,155,158,
|
||||
161,164,166,169,171,174,176,178,181,183,185,187,189,191,193,194,196,198,
|
||||
199,201,202,203,204,205,206,207,208,209,209,210,211,211,211,212,212,212,
|
||||
212,212,212,212,212,211,211,211,210,210,210,209,208,208,207,207,206,205,
|
||||
205,204,203,203,202,201,201,200,199,199,198,197,197,196,196,195,195,194,
|
||||
194,194,193,193,193,193,193,193,193,193,193,193,194,194,195,195,196,196,
|
||||
197,198,199,200,200,202,203,204,205,206,208,209,210,212,213,215,217,218,
|
||||
220,222,223,225,227,229,231,232,234,236,238,240,242,244,245,247,249,251,
|
||||
253,255],
|
||||
g: [0,0,1,1,2,2,3,4,4,5,6,6,7,8,9,10,
|
||||
11,11,12,13,14,15,17,18,19,20,21,22,24,25,26,28,29,31,32,34,35,37,38,40,
|
||||
41,43,45,46,48,50,52,53,55,57,58,60,62,64,66,67,69,71,73,74,76,78,79,81,
|
||||
83,84,86,88,89,91,92,94,95,97,98,99,101,102,103,104,106,107,108,109,110,
|
||||
111,112,113,114,114,115,116,116,117,118,118,119,119,120,120,120,121,121,
|
||||
121,121,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,121,
|
||||
121,121,121,121,121,121,121,121,120,120,120,120,120,120,120,120,120,120,
|
||||
121,121,121,121,121,122,122,122,123,123,124,124,125,125,126,127,127,128,
|
||||
129,130,131,131,132,133,135,136,137,138,139,140,142,143,144,146,147,149,
|
||||
150,152,154,155,157,158,160,162,164,165,167,169,171,172,174,176,178,180,
|
||||
182,183,185,187,189,191,193,194,196,198,200,202,203,205,207,208,210,212,
|
||||
213,215,216,218,219,221,222,224,225,226,228,229,230,231,232,233,235,236,
|
||||
237,238,239,240,240,241,242,243,244,244,245,246,247,247,248,248,249,250,
|
||||
250,251,251,252,252,253,253,254,255],
|
||||
b: [0,1,3,4,6,8,9,11,13,15,17,19,21,23,
|
||||
25,27,29,31,33,35,37,39,41,43,45,47,48,50,52,54,56,57,59,60,62,63,65,66,
|
||||
67,69,70,71,72,73,74,74,75,76,76,77,77,77,78,78,78,78,78,78,78,77,77,77,
|
||||
76,76,75,75,74,73,73,72,71,70,69,68,67,66,66,65,64,63,61,60,59,58,58,57,
|
||||
56,55,54,53,52,51,51,50,49,49,48,48,47,47,47,46,46,46,46,46,47,47,47,48,
|
||||
48,49,50,50,51,52,53,55,56,57,59,60,62,64,65,67,69,71,74,76,78,81,83,86,
|
||||
88,91,94,96,99,102,105,108,111,114,117,120,124,127,130,133,136,140,143,
|
||||
146,149,153,156,159,162,165,169,172,175,178,181,184,186,189,192,195,197,
|
||||
200,203,205,207,210,212,214,216,218,220,222,224,226,227,229,230,231,233,
|
||||
234,235,236,237,238,239,239,240,241,241,242,242,242,243,243,243,243,243,
|
||||
243,243,243,243,243,242,242,242,242,241,241,241,241,240,240,240,239,239,
|
||||
239,239,239,238,238,238,238,238,238,238,238,239,239,239,240,240,240,241,
|
||||
242,242,243,244,245,246,247,248,249,250,252,253,255]
|
||||
};
|
||||
|
||||
|
||||
|
||||
ColorMap.MAPS_CUSTOM = ['cubehelix', 'eosb', 'rainbow'];
|
||||
ColorMap.MAPS_NAMES = ['native', 'grayscale'].concat(ColorMap.MAPS_CUSTOM);
|
||||
|
||||
ColorMap.prototype.reverse = function(val) {
|
||||
if (val) {
|
||||
this.reversed = val;
|
||||
}
|
||||
else {
|
||||
this.reversed = ! this.reversed;
|
||||
}
|
||||
this.sig = this.signature();
|
||||
this.view.requestRedraw();
|
||||
};
|
||||
|
||||
|
||||
ColorMap.prototype.signature = function() {
|
||||
var s = this.mapName;
|
||||
|
||||
if (this.reversed) {
|
||||
s += ' reversed';
|
||||
}
|
||||
|
||||
return s;
|
||||
};
|
||||
|
||||
ColorMap.prototype.update = function(mapName) {
|
||||
this.mapName = mapName;
|
||||
this.sig = this.signature();
|
||||
this.view.requestRedraw();
|
||||
};
|
||||
|
||||
ColorMap.prototype.apply = function(img) {
|
||||
if ( this.sig=='native' ) {
|
||||
return img;
|
||||
}
|
||||
|
||||
if (img.cmSig==this.sig) {
|
||||
return img.cmImg; // return cached pixels
|
||||
}
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
var pixelData = imageData.data;
|
||||
var length = pixelData.length;
|
||||
var a, b, c;
|
||||
var switchCase = 3;
|
||||
if (this.mapName=='grayscale') {
|
||||
switchCase = 1;
|
||||
}
|
||||
else if (ColorMap.MAPS_CUSTOM.indexOf(this.mapName)>=0) {
|
||||
switchCase = 2;
|
||||
}
|
||||
for (var i = 0; i < length; i+= 4) {
|
||||
switch(switchCase) {
|
||||
case 1:
|
||||
a = b = c = AladinUtils.myRound((pixelData[i]+pixelData[i+1]+pixelData[i+2])/3);
|
||||
break;
|
||||
case 2:
|
||||
if (this.reversed) {
|
||||
a = ColorMap.MAPS[this.mapName].r[255-pixelData[i]];
|
||||
b = ColorMap.MAPS[this.mapName].g[255-pixelData[i+1]];
|
||||
c = ColorMap.MAPS[this.mapName].b[255-pixelData[i+2]];
|
||||
}
|
||||
else {
|
||||
a = ColorMap.MAPS[this.mapName].r[pixelData[i]];
|
||||
b = ColorMap.MAPS[this.mapName].g[pixelData[i+1]];
|
||||
c = ColorMap.MAPS[this.mapName].b[pixelData[i+2]];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
a = pixelData[i];
|
||||
b = pixelData[i + 1];
|
||||
c = pixelData[i + 2];
|
||||
|
||||
}
|
||||
if (switchCase!=2 && this.reversed) {
|
||||
a = 255-a;
|
||||
b = 255-b;
|
||||
c = 255-c;
|
||||
|
||||
}
|
||||
pixelData[i] = a;
|
||||
pixelData[i + 1] = b;
|
||||
pixelData[i + 2] = c;
|
||||
|
||||
}
|
||||
//imageData.data = pixelData; // not needed, and create an error in strict mode !
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
// cache image with color map applied
|
||||
img.cmSig = this.sig;
|
||||
img.cmImg = canvas;
|
||||
|
||||
return img.cmImg;
|
||||
};
|
||||
|
||||
return ColorMap;
|
||||
})();
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
import { GenericPointer } from "./GenericPointer.js";
|
||||
import A from "./A.js";
|
||||
import { CatalogQueryBox } from "./gui/Box/CatalogQueryBox.js";
|
||||
import cameraIconUrl from '../../assets/icons/camera.svg'
|
||||
import targetIconUrl from '../../assets/icons/target.svg';
|
||||
import uploadIconUrl from '../../assets/icons/upload.svg';
|
||||
|
||||
export let DefaultActionsForContextMenu = (function () {
|
||||
|
||||
@@ -48,38 +45,31 @@ export let DefaultActionsForContextMenu = (function () {
|
||||
return [
|
||||
{
|
||||
label: "Copy position", action(o) {
|
||||
let msg;
|
||||
navigator.clipboard.writeText(o.target.innerText)
|
||||
.then(() => {
|
||||
msg = 'successful'
|
||||
if (aladinInstance.statusBar) {
|
||||
aladinInstance.statusBar.appendMessage({
|
||||
message: 'Reticle location saved!',
|
||||
duration: 2000,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
msg = 'unsuccessful'
|
||||
console.info('Oops, unable to copy', e);
|
||||
})
|
||||
.finally(() => {
|
||||
console.info('Copying text command was ' + msg);
|
||||
var r = document.createRange();
|
||||
r.selectNode(o.target);
|
||||
window.getSelection().removeAllRanges();
|
||||
window.getSelection().addRange(r);
|
||||
let statusBarMsg;
|
||||
try {
|
||||
let successful = document.execCommand('copy');
|
||||
statusBarMsg = successful ? 'Position copied!' : 'Position could not be copied!';
|
||||
} catch (err) {
|
||||
statusBarMsg = 'Oops, unable to copy to clipboard';
|
||||
}
|
||||
|
||||
if (a.statusBar) {
|
||||
a.statusBar.appendMessage({
|
||||
message: statusBarMsg,
|
||||
duration: 2000,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: {
|
||||
icon: {
|
||||
tooltip: {content: 'Download a PNG image file of the view', position: {direction: 'top'}},
|
||||
monochrome: true,
|
||||
url: cameraIconUrl,
|
||||
size: 'small',
|
||||
},
|
||||
content: 'Take a snapshot'
|
||||
},
|
||||
action(o) { a.exportAsPNG(); }
|
||||
label: "Take snapshot", action(o) { a.exportAsPNG(); }
|
||||
},
|
||||
{
|
||||
label: "Add",
|
||||
@@ -95,30 +85,23 @@ export let DefaultActionsForContextMenu = (function () {
|
||||
{
|
||||
label: 'New catalogue layer', action(o) {
|
||||
let catBox = new CatalogQueryBox(a)
|
||||
catBox._show({
|
||||
header: {
|
||||
title: 'Add a new catalogue',
|
||||
draggable: true
|
||||
},
|
||||
position: {
|
||||
anchor :'center center'
|
||||
},
|
||||
});
|
||||
if (catBox.isHidden) {
|
||||
catBox._show({
|
||||
header: {
|
||||
title: 'Add a new catalogue',
|
||||
draggable: true
|
||||
},
|
||||
position: {
|
||||
anchor :'center center'
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: {
|
||||
icon: {
|
||||
monochrome: true,
|
||||
url: uploadIconUrl,
|
||||
cssStyle: {
|
||||
cursor: 'help',
|
||||
}
|
||||
},
|
||||
content: "Load a local file"
|
||||
},
|
||||
label: "Load local file",
|
||||
subMenu: [
|
||||
{
|
||||
label: 'FITS image', action(o) {
|
||||
@@ -186,21 +169,8 @@ export let DefaultActionsForContextMenu = (function () {
|
||||
]
|
||||
},
|
||||
{
|
||||
label: {
|
||||
icon: {
|
||||
tooltip: {content: 'Use Sesame, our name resolver!', position: {direction: 'top'}},
|
||||
monochrome: true,
|
||||
url: targetIconUrl,
|
||||
size: 'small',
|
||||
},
|
||||
content: 'What is this?'
|
||||
},
|
||||
|
||||
action(o, ctxMenu) {
|
||||
GenericPointer(a.view, {
|
||||
x: parseInt(ctxMenu.element().style.left),
|
||||
y: parseInt(ctxMenu.element().style.top)
|
||||
});
|
||||
label: "What is this?", action(o) {
|
||||
GenericPointer(a.view, o);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -41,8 +41,6 @@ export let Ellipse = (function() {
|
||||
this.color = options['color'] || undefined;
|
||||
this.fillColor = options['fillColor'] || undefined;
|
||||
this.lineWidth = options["lineWidth"] || 2;
|
||||
this.selectionColor = options["selectionColor"] || '#00ff00';
|
||||
this.hoverColor = options["hoverColor"] || undefined;
|
||||
|
||||
// TODO : all graphic overlays should have an id
|
||||
this.id = 'ellipse-' + Utils.uuidv4();
|
||||
@@ -54,7 +52,8 @@ export let Ellipse = (function() {
|
||||
|
||||
this.isShowing = true;
|
||||
this.isSelected = false;
|
||||
this.isHovered = false;
|
||||
|
||||
this.selectionColor = '#00ff00';
|
||||
};
|
||||
|
||||
Ellipse.prototype.setColor = function(color) {
|
||||
@@ -77,16 +76,6 @@ export let Ellipse = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
Ellipse.prototype.setHoverColor = function(color) {
|
||||
if (this.hoverColor == color) {
|
||||
return;
|
||||
}
|
||||
this.hoverColor = color;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
};
|
||||
|
||||
Ellipse.prototype.setLineWidth = function(lineWidth) {
|
||||
if (this.lineWidth == lineWidth) {
|
||||
return;
|
||||
@@ -146,25 +135,6 @@ export let Ellipse = (function() {
|
||||
};
|
||||
|
||||
|
||||
Ellipse.prototype.hover = function() {
|
||||
if (this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = true;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
Ellipse.prototype.unhover = function() {
|
||||
if (! this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = false;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
Ellipse.prototype.setCenter = function(centerRaDec) {
|
||||
this.centerRaDec = centerRaDec;
|
||||
@@ -251,9 +221,8 @@ export let Ellipse = (function() {
|
||||
} else {
|
||||
ctx.strokeStyle = Overlay.increaseBrightness(baseColor, 50);
|
||||
}
|
||||
} else if (this.isHovered) {
|
||||
ctx.strokeStyle = this.hoverColor || Overlay.increaseBrightness(baseColor, 25);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
ctx.strokeStyle = baseColor;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
import { FSM } from "../FiniteStateMachine";
|
||||
import { View } from "../View";
|
||||
import { Selector } from "../Selector";
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
@@ -84,8 +83,7 @@ export class CircleSelect extends FSM {
|
||||
|
||||
x = this.startCoo.x;
|
||||
y = this.startCoo.y;
|
||||
|
||||
let s = {
|
||||
(typeof this.callback === 'function') && this.callback({
|
||||
x, y, r,
|
||||
label: 'circle',
|
||||
contains(s) {
|
||||
@@ -102,24 +100,21 @@ export class CircleSelect extends FSM {
|
||||
h: 2*r
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// execute general callback
|
||||
if (view.aladin.callbacksByEventName) {
|
||||
var callback = view.aladin.callbacksByEventName['select'];
|
||||
if (typeof callback === "function") {
|
||||
let objList = Selector.getObjects(s, view);
|
||||
callback(objList);
|
||||
}
|
||||
}
|
||||
|
||||
// execute selection callback only
|
||||
(typeof this.callback === 'function') && this.callback(s);
|
||||
});
|
||||
|
||||
// TODO: remove these modes in the future
|
||||
view.aladin.showReticle(true)
|
||||
view.setCursor('default');
|
||||
|
||||
// execute general callback
|
||||
if (view.callbacksByEventName) {
|
||||
var callback = view.callbacksByEventName['select'];
|
||||
if (typeof callback === "function") {
|
||||
// !todo
|
||||
let selectedObjects = view.selectObjects(this);
|
||||
callback(selectedObjects);
|
||||
}
|
||||
}
|
||||
view.setMode(View.PAN)
|
||||
view.requestRedraw();
|
||||
};
|
||||
|
||||
@@ -163,23 +163,13 @@ export class PolySelect extends FSM {
|
||||
let y = yMin;
|
||||
let w = xMax - xMin;
|
||||
let h = yMax - yMin;
|
||||
|
||||
let s = {
|
||||
(typeof this.callback === 'function') && this.callback({
|
||||
vertices: this.coos,
|
||||
label: 'polygon',
|
||||
bbox() {
|
||||
return {x, y, w, h}
|
||||
}
|
||||
};
|
||||
(typeof this.callback === 'function') && this.callback(s);
|
||||
|
||||
// execute general callback
|
||||
if (view.aladin.callbacksByEventName) {
|
||||
var callback = view.aladin.callbacksByEventName['select'];
|
||||
if (typeof callback === "function") {
|
||||
console.warn('polygon selection is not fully implemented, PolySelect.contains is needed for finding sources inside a polygon')
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.coos = [];
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
import { FSM } from "../FiniteStateMachine";
|
||||
import { View } from "../View";
|
||||
import { Selector } from "../Selector";
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
@@ -92,7 +91,7 @@ export class RectSelect extends FSM {
|
||||
h = -h;
|
||||
}
|
||||
|
||||
let s = {
|
||||
(typeof this.callback === 'function') && this.callback({
|
||||
x, y, w, h,
|
||||
label: 'rect',
|
||||
contains(s) {
|
||||
@@ -101,20 +100,21 @@ export class RectSelect extends FSM {
|
||||
bbox() {
|
||||
return {x, y, w, h}
|
||||
}
|
||||
};
|
||||
|
||||
(typeof this.callback === 'function') && this.callback(s);
|
||||
});
|
||||
|
||||
// TODO: remove these modes in the future
|
||||
view.aladin.showReticle(true)
|
||||
view.setCursor('default');
|
||||
|
||||
// execute general callback
|
||||
if (view.aladin.callbacksByEventName) {
|
||||
var callback = view.aladin.callbacksByEventName['select'];
|
||||
if (view.callbacksByEventName) {
|
||||
var callback = view.callbacksByEventName['select'];
|
||||
if (typeof callback === "function") {
|
||||
let objList = Selector.getObjects(s, view);
|
||||
callback(objList);
|
||||
// !todo
|
||||
let selectedObjects = view.selectObjects(this);
|
||||
console.log(selectedObjects)
|
||||
|
||||
callback(selectedObjects);
|
||||
}
|
||||
}
|
||||
view.setMode(View.PAN)
|
||||
|
||||
@@ -46,7 +46,6 @@ export let Footprint= (function() {
|
||||
this.shapes = shapes;
|
||||
|
||||
this.isShowing = true;
|
||||
this.isHovered = false;
|
||||
|
||||
this.overlay = null;
|
||||
};
|
||||
@@ -83,36 +82,6 @@ export let Footprint= (function() {
|
||||
this.shapes.forEach((shape) => shape.deselect())
|
||||
};
|
||||
|
||||
Footprint.prototype.hover = function() {
|
||||
if (this.isHovered) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isHovered = true;
|
||||
this.shapes.forEach((shape) => shape.hover())
|
||||
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
} else if (this.source && this.source.catalog) {
|
||||
this.source.catalog.view && this.source.catalog.view.requestRedraw();
|
||||
}
|
||||
};
|
||||
|
||||
Footprint.prototype.unhover = function() {
|
||||
if (!this.isHovered) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isHovered = false;
|
||||
this.shapes.forEach((shape) => shape.unhover())
|
||||
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
} else if (this.source && this.source.catalog) {
|
||||
this.source.catalog.view && this.source.catalog.view.requestRedraw();
|
||||
}
|
||||
};
|
||||
|
||||
Footprint.prototype.setLineWidth = function(lineWidth) {
|
||||
this.shapes.forEach((shape) => shape.setLineWidth(lineWidth))
|
||||
};
|
||||
@@ -131,10 +100,6 @@ export let Footprint= (function() {
|
||||
this.shapes.forEach((shape) => shape.setSelectionColor(color))
|
||||
};
|
||||
|
||||
Footprint.prototype.setHoverColor = function(color) {
|
||||
this.shapes.forEach((shape) => shape.setHoverColor(color))
|
||||
};
|
||||
|
||||
Footprint.prototype.isFootprint = function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,14 +11,9 @@ import { Utils } from './Utils';
|
||||
|
||||
// allow to call either Simbad or Planetary features Pointers
|
||||
export let GenericPointer = function (view, e) {
|
||||
let xymouse;
|
||||
if (e instanceof Event) {
|
||||
xymouse = Utils.relMouseCoords(e);
|
||||
} else {
|
||||
xymouse = e;
|
||||
}
|
||||
const xymouse = Utils.relMouseCoords(e);
|
||||
|
||||
let radec = view.aladin.pix2world(xymouse.x, xymouse.y, 'icrs');
|
||||
let radec = view.aladin.pix2world(xymouse.x, xymouse.y);
|
||||
if (radec) {
|
||||
// sky case
|
||||
if (view.aladin.getBaseImageLayer().isPlanetaryBody() === false) {
|
||||
@@ -28,7 +23,7 @@ export let GenericPointer = function (view, e) {
|
||||
// planetary body case
|
||||
else {
|
||||
// TODO: replace with actual value
|
||||
const body = view.aladin.getBaseImageLayer().hipsBody;
|
||||
const body = view.aladin.getBaseImageLayer().properties.hipsBody;
|
||||
PlanetaryFeaturesPointer.query(radec[0], radec[1], Math.min(80, view.fov / 20.0), body, view.aladin);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -65,6 +65,7 @@ HiPSProperties.fetchFromID = async function(ID) {
|
||||
// Exactly one matching
|
||||
result = metadata[0];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -73,7 +74,7 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
try {
|
||||
urlOrId = new URL(urlOrId);
|
||||
} catch (e) {
|
||||
// Relative path test
|
||||
// Relative path
|
||||
try {
|
||||
urlOrId = Utils.getAbsoluteURL(urlOrId)
|
||||
|
||||
@@ -134,36 +135,27 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
return result;
|
||||
}
|
||||
|
||||
HiPSProperties.getFasterMirrorUrl = function (metadata, currUrl) {
|
||||
const pingHiPSServiceUrl = async (baseUrl) => {
|
||||
baseUrl = Utils.fixURLForHTTPS(baseUrl);
|
||||
HiPSProperties.getFasterMirrorUrl = function (metadata) {
|
||||
const pingHiPSServiceUrl = (hipsServiceUrl) => {
|
||||
hipsServiceUrl = Utils.fixURLForHTTPS(hipsServiceUrl);
|
||||
|
||||
const controller = new AbortController()
|
||||
|
||||
const maxTime = 1000;
|
||||
let startRequestTime = Date.now();
|
||||
const maxTime = 500;
|
||||
// 5 second timeout:
|
||||
const timeoutId = setTimeout(() => controller.abort(), maxTime)
|
||||
|
||||
let startRequestTime = performance.now();
|
||||
let options = {
|
||||
//headers: { 'Cache-Control': 'no-cache' }, // Disable caching
|
||||
method: 'GET',
|
||||
signal: controller.signal,
|
||||
mode: 'cors',
|
||||
cache: "no-cache",
|
||||
};
|
||||
let validRequest = await fetch(baseUrl + '/properties', options).then((resp) => {
|
||||
const promise = fetch(hipsServiceUrl + '/properties', { cache: 'no-store', signal: controller.signal, mode: "cors" }).then(response => {
|
||||
const duration = Date.now() - startRequestTime;//the time needed to do the request
|
||||
// completed request before timeout fired
|
||||
clearTimeout(timeoutId)
|
||||
// Resolve with the time duration of the request
|
||||
return Promise.resolve(true);
|
||||
return { duration: duration, baseUrl: hipsServiceUrl, validRequest: true };
|
||||
}).catch((e) => {
|
||||
return Promise.resolve(false);
|
||||
return { duration: maxTime, baseUrl: hipsServiceUrl, validRequest: false };
|
||||
});
|
||||
const duration = performance.now() - startRequestTime;//the time needed to do the request
|
||||
|
||||
|
||||
return {duration, validRequest, baseUrl};
|
||||
return promise;
|
||||
};
|
||||
|
||||
// Get all the possible hips_service_url urls
|
||||
@@ -200,38 +192,21 @@ HiPSProperties.getFasterMirrorUrl = function (metadata, currUrl) {
|
||||
});
|
||||
|
||||
//console.log(validResponses)
|
||||
let newUrlResp;
|
||||
|
||||
if (validResponses.length >= 2) {
|
||||
const isSecondUrlOk = ((validResponses[1].duration - validResponses[0].duration) / validResponses[0].duration) < 0.10;
|
||||
const isSecondUrlOk = ((validResponses[1].duration - validResponses[0].duration) / validResponses[0].duration) < 0.20;
|
||||
|
||||
if (isSecondUrlOk) {
|
||||
newUrlResp = validResponses[getRandomIntInclusive(0, 1)];
|
||||
return validResponses[getRandomIntInclusive(0, 1)].baseUrl;
|
||||
} else {
|
||||
newUrlResp = validResponses[0];
|
||||
return validResponses[0].baseUrl;
|
||||
}
|
||||
} else if (validResponses.length === 1) {
|
||||
newUrlResp = validResponses[0];
|
||||
return validResponses[0].baseUrl;
|
||||
} else {
|
||||
// no valid response => we return an error
|
||||
return Promise.reject('Survey not found. All mirrors urls have been tested:' + urls)
|
||||
}
|
||||
|
||||
// check if there is a big difference from the current one
|
||||
let currUrlResp = validResponses.find((r) => r.baseUrl === currUrl)
|
||||
|
||||
let urlChosen;
|
||||
if (Math.abs(currUrlResp.duration - newUrlResp.duration) / Math.min(currUrlResp.duration, newUrlResp.duration) < 0.10) {
|
||||
// there is not enough difference => do not switch
|
||||
urlChosen = currUrlResp.baseUrl;
|
||||
} else {
|
||||
// good difference we take the best
|
||||
urlChosen = newUrlResp.baseUrl;
|
||||
}
|
||||
|
||||
//console.log('curr url', currUrlResp, ', new ', newUrlResp)
|
||||
|
||||
urlChosen = Utils.fixURLForHTTPS(urlChosen)
|
||||
return urlChosen;
|
||||
})
|
||||
.then((url) => Utils.fixURLForHTTPS(url))
|
||||
}
|
||||
|
||||
@@ -29,11 +29,15 @@
|
||||
*****************************************************************************/
|
||||
import { ALEvent } from "./events/ALEvent.js";
|
||||
import { ColorCfg } from "./ColorCfg.js";
|
||||
import { ImageLayer } from "./ImageLayer.js";
|
||||
import { Utils } from "./Utils";
|
||||
|
||||
export let ImageFITS = (function () {
|
||||
|
||||
function ImageFITS(url, name, options, successCallback = undefined, errorCallback = undefined) {
|
||||
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;
|
||||
@@ -42,102 +46,110 @@ export let ImageFITS = (function () {
|
||||
this.url = url.toString();
|
||||
|
||||
this.id = url.toString();
|
||||
this.name = name || this.url;
|
||||
this.name = name;
|
||||
|
||||
this.imgFormat = "fits";
|
||||
this.formats = ["fits"]
|
||||
this.properties = {
|
||||
formats: ["fits"]
|
||||
}
|
||||
// callbacks
|
||||
this.successCallback = successCallback;
|
||||
this.errorCallback = errorCallback;
|
||||
// initialize the color meta data here
|
||||
// set a asinh stretch by default if there is none
|
||||
/*if (options) {
|
||||
if (options) {
|
||||
options.stretch = options.stretch || "asinh";
|
||||
}*/
|
||||
}
|
||||
this.colorCfg = new ColorCfg(options);
|
||||
|
||||
let self = this;
|
||||
|
||||
this.query = Promise.resolve(self);
|
||||
}
|
||||
|
||||
// A cache storing directly the images to not query for the properties each time
|
||||
ImageFITS.cache = {};
|
||||
updateMetadata(self);
|
||||
ImageLayer.update(self);
|
||||
|
||||
ImageFITS.prototype.setView = function(view) {
|
||||
this.view = view;
|
||||
this.query = Promise.resolve(self);
|
||||
}
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setOpacity = function (opacity) {
|
||||
let self = this;
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(self, () => {
|
||||
self.colorCfg.setOpacity(opacity);
|
||||
});
|
||||
};
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setBlendingConfig = function (additive = false) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setBlendingConfig(additive);
|
||||
});
|
||||
};
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setColormap = function (colormap, options) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setColormap(colormap, options);
|
||||
});
|
||||
}
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setCuts = function (lowCut, highCut) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setCuts(lowCut, highCut);
|
||||
});
|
||||
};
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setGamma = function (gamma) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setGamma(gamma);
|
||||
});
|
||||
};
|
||||
|
||||
ImageFITS.prototype.getAvailableFormats = function() {
|
||||
return this.properties.formats;
|
||||
}
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setSaturation = function (saturation) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setSaturation(saturation);
|
||||
});
|
||||
};
|
||||
|
||||
ImageFITS.prototype.setBrightness = function (brightness) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setBrightness(brightness);
|
||||
});
|
||||
};
|
||||
|
||||
ImageFITS.prototype.setContrast = function (contrast) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg.setContrast(contrast);
|
||||
});
|
||||
};
|
||||
|
||||
ImageFITS.prototype.metadata = function () {
|
||||
return {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: false,
|
||||
imgFormat: this.imgFormat
|
||||
};
|
||||
}
|
||||
|
||||
// Private method for updating the view with the new meta
|
||||
ImageFITS.prototype._updateMetadata = function (callback) {
|
||||
var updateMetadata = function (self, callback = undefined) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
// Tell the view its meta have changed
|
||||
try {
|
||||
if (this.added) {
|
||||
this.view.wasm.setImageMetadata(this.layer, {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: false,
|
||||
imgFormat: this.imgFormat
|
||||
});
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(this.view.aladinDiv, { layer: this });
|
||||
if (self.added) {
|
||||
const metadata = self.metadata();
|
||||
self.wasm.setImageMetadata(self.layer, metadata);
|
||||
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(self.view.aladinDiv, { layer: self });
|
||||
}
|
||||
} catch (e) {
|
||||
// Display the error message
|
||||
@@ -149,19 +161,13 @@ export let ImageFITS = (function () {
|
||||
this.layer = layer;
|
||||
|
||||
let self = this;
|
||||
|
||||
const promise = self.view.wasm.addImageFITS({
|
||||
const promise = self.wasm.addImageFITS({
|
||||
layer: self.layer,
|
||||
url: self.url,
|
||||
meta: {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: false,
|
||||
imgFormat: this.imgFormat
|
||||
}
|
||||
meta: self.metadata()
|
||||
}).then((imagesParams) => {
|
||||
// There is at least one entry in imageParams
|
||||
self.added = true;
|
||||
|
||||
self.children = [];
|
||||
|
||||
let hduIdx = 0;
|
||||
@@ -170,6 +176,7 @@ export let ImageFITS = (function () {
|
||||
let image = new ImageFITS(
|
||||
imageParams.url,
|
||||
self.name + "_ext_" + hduIdx.toString(),
|
||||
self.view,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
@@ -178,7 +185,6 @@ export let ImageFITS = (function () {
|
||||
// Set the layer corresponding to the onein the backend
|
||||
image.layer = imageParams.layer;
|
||||
image.added = true;
|
||||
image.setView(self.view);
|
||||
// deep copy of the color object of self
|
||||
image.colorCfg = Utils.deepCopy(self.colorCfg);
|
||||
// Set the automatic computed cuts
|
||||
@@ -209,6 +215,8 @@ export let ImageFITS = (function () {
|
||||
|
||||
return self;
|
||||
}).catch((e) => {
|
||||
window.alert(e + ". See the javascript console for more logging details.")
|
||||
|
||||
if (self.errorCallback) {
|
||||
self.errorCallback()
|
||||
}
|
||||
@@ -251,7 +259,7 @@ export let ImageFITS = (function () {
|
||||
ImageFITS.prototype.setAlpha = ImageFITS.prototype.setOpacity;
|
||||
|
||||
ImageFITS.prototype.setColorCfg = function (colorCfg) {
|
||||
this._updateMetadata(() => {
|
||||
updateMetadata(this, () => {
|
||||
this.colorCfg = colorCfg;
|
||||
});
|
||||
};
|
||||
@@ -275,7 +283,7 @@ export let ImageFITS = (function () {
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.readPixel = function (x, y) {
|
||||
return this.view.wasm.readPixel(x, y, this.layer);
|
||||
return this.wasm.readPixel(x, y, this.layer);
|
||||
};
|
||||
|
||||
return ImageFITS;
|
||||
|
||||
218
src/js/ImageLayer.js
Normal file
218
src/js/ImageLayer.js
Normal file
@@ -0,0 +1,218 @@
|
||||
export let ImageLayer = {};
|
||||
|
||||
ImageLayer.update = function (layer) {
|
||||
const foundLayer = ImageLayer.contains(layer.id)
|
||||
|
||||
const options = layer.metadata;
|
||||
// The survey has not been found among the ones cached
|
||||
if (foundLayer) {
|
||||
foundLayer.options = options;
|
||||
} else {
|
||||
ImageLayer.LAYERS.push({
|
||||
id: layer.id,
|
||||
name: layer.name,
|
||||
url: layer.url,
|
||||
options,
|
||||
subtype: layer.subtype,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ImageLayer.contains = function(id) {
|
||||
return ImageLayer.LAYERS.find((layer) => layer.id.endsWith(id));
|
||||
}
|
||||
|
||||
ImageLayer.DEFAULT_SURVEY = {
|
||||
id: "P/DSS2/color",
|
||||
name: "DSS colored",
|
||||
url: "https://alasky.cds.unistra.fr/DSS/DSSColor",
|
||||
maxOrder: 9,
|
||||
subtype: "survey",
|
||||
tileSize: 512,
|
||||
formats: ['jpeg'],
|
||||
creatorDid: "ivo://CDS/P/DSS2/color",
|
||||
dataproductSubtype: ['color'],
|
||||
frame: "ICRS"
|
||||
}
|
||||
|
||||
ImageLayer.LAYERS = [
|
||||
ImageLayer.DEFAULT_SURVEY,
|
||||
{
|
||||
id: "P/2MASS/color",
|
||||
name: "2MASS colored",
|
||||
url: "https://alasky.cds.unistra.fr/2MASS/Color",
|
||||
maxOrder: 9,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/DSS2/red",
|
||||
name: "DSS2 Red (F+R)",
|
||||
url: "https://alasky.cds.unistra.fr/DSS/DSS2Merged",
|
||||
maxOrder: 9,
|
||||
subtype: "survey",
|
||||
// options
|
||||
options: {
|
||||
minCut: 1000.0,
|
||||
maxCut: 10000.0,
|
||||
colormap: "magma",
|
||||
stretch: 'Linear',
|
||||
imgFormat: "fits"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "P/DM/I/350/gaiaedr3",
|
||||
name: "Density map for Gaia EDR3 (I/350/gaiaedr3)",
|
||||
url: "https://alasky.cds.unistra.fr/ancillary/GaiaEDR3/density-map",
|
||||
maxOrder: 7,
|
||||
subtype: "survey",
|
||||
// options
|
||||
options: {
|
||||
minCut: 0,
|
||||
maxCut: 12000,
|
||||
stretch: 'asinh',
|
||||
colormap: "rdylbu",
|
||||
imgFormat: "fits",
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "P/PanSTARRS/DR1/g",
|
||||
name: "PanSTARRS DR1 g",
|
||||
url: "https://alasky.cds.unistra.fr/Pan-STARRS/DR1/g",
|
||||
maxOrder: 11,
|
||||
subtype: "survey",
|
||||
// options
|
||||
options: {
|
||||
minCut: -34,
|
||||
maxCut: 7000,
|
||||
stretch: 'asinh',
|
||||
colormap: "redtemperature",
|
||||
imgFormat: "fits",
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "P/PanSTARRS/DR1/color-z-zg-g",
|
||||
name: "PanSTARRS DR1 color",
|
||||
url: "https://alasky.cds.unistra.fr/Pan-STARRS/DR1/color-z-zg-g",
|
||||
maxOrder: 11,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/DECaPS/DR1/color",
|
||||
name: "DECaPS DR1 color",
|
||||
url: "https://alasky.cds.unistra.fr/DECaPS/DR1/color",
|
||||
maxOrder: 11,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/Fermi/color",
|
||||
name: "Fermi color",
|
||||
url: "https://alasky.cds.unistra.fr/Fermi/Color",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/Finkbeiner",
|
||||
name: "Halpha",
|
||||
url: "https://alasky.cds.unistra.fr/FinkbeinerHalpha",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
// options
|
||||
options: {
|
||||
minCut: -10,
|
||||
maxCut: 800,
|
||||
colormap: "rdbu",
|
||||
imgFormat: "fits",
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "P/GALEXGR6_7/NUV",
|
||||
name: "GALEXGR6_7 NUV",
|
||||
url: "http://alasky.cds.unistra.fr/GALEX/GALEXGR6_7_NUV/",
|
||||
maxOrder: 8,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/IRIS/color",
|
||||
name: "IRIS colored",
|
||||
url: "https://alasky.cds.unistra.fr/IRISColor",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/Mellinger/color",
|
||||
name: "Mellinger colored",
|
||||
url: "https://alasky.cds.unistra.fr/MellingerRGB",
|
||||
maxOrder: 4,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/SDSS9/color",
|
||||
name: "SDSS9 colored",
|
||||
url: "https://alasky.cds.unistra.fr/SDSS/DR9/color",
|
||||
maxOrder: 10,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/SDSS9/g",
|
||||
name: "SDSS9 band-g",
|
||||
url: "https://alasky.cds.unistra.fr/SDSS/DR9/band-g",
|
||||
maxOrder: 10,
|
||||
subtype: "survey",
|
||||
options: {
|
||||
stretch: 'asinh',
|
||||
colormap: "redtemperature",
|
||||
imgFormat: 'fits'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "P/SPITZER/color",
|
||||
name: "IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)",
|
||||
url: "http://alasky.cds.unistra.fr/Spitzer/SpitzerI1I2I4color/",
|
||||
maxOrder: 9,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/VTSS/Ha",
|
||||
name: "VTSS-Ha",
|
||||
url: "https://alasky.cds.unistra.fr/VTSS/Ha",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
options: {
|
||||
minCut: -10.0,
|
||||
maxCut: 100.0,
|
||||
colormap: "grayscale",
|
||||
imgFormat: "fits"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "xcatdb/P/XMM/PN/color",
|
||||
name: "XMM PN colored",
|
||||
url: "https://alasky.cds.unistra.fr/cgi/JSONProxy?url=https://saada.unistra.fr/PNColor",
|
||||
maxOrder: 7,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/allWISE/color",
|
||||
name: "AllWISE color",
|
||||
url: "https://alasky.cds.unistra.fr/AllWISE/RGB-W4-W2-W1/",
|
||||
maxOrder: 8,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/GLIMPSE360",
|
||||
name: "GLIMPSE360",
|
||||
// This domain is not giving the CORS headers
|
||||
// We need to query by with a proxy equipped with CORS header.
|
||||
url: "https://alasky.cds.unistra.fr/cgi/JSONProxy?url=https://www.spitzer.caltech.edu/glimpse360/aladin/data",
|
||||
subtype: "survey",
|
||||
options: {
|
||||
maxOrder: 9,
|
||||
imgFormat: "jpg",
|
||||
minOrder: 3,
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
ImageLayer.getAvailableLayers = function () {
|
||||
return ImageLayer.LAYERS;
|
||||
};
|
||||
@@ -30,13 +30,14 @@
|
||||
import { Utils } from "./Utils";
|
||||
import { ALEvent } from "./events/ALEvent.js";
|
||||
import { ColorCfg } from "./ColorCfg.js";
|
||||
import { ImageLayer } from "./ImageLayer.js";
|
||||
import { HiPSProperties } from "./HiPSProperties.js";
|
||||
|
||||
let PropertyParser = {};
|
||||
// Utilitary functions for parsing the properties and giving default values
|
||||
/// Mandatory tileSize property
|
||||
PropertyParser.tileSize = function(properties) {
|
||||
let tileSize = (properties && properties.hips_tile_width && (+properties.hips_tile_width)) || 512;
|
||||
PropertyParser.tileSize = function(options, properties = {}) {
|
||||
let tileSize = (options && options.tileSize) || (properties.hips_tile_width && (+properties.hips_tile_width)) || 512;
|
||||
|
||||
// Check if the tile width size is a power of 2
|
||||
if (tileSize & (tileSize - 1) !== 0) {
|
||||
@@ -47,25 +48,35 @@ PropertyParser.tileSize = function(properties) {
|
||||
}
|
||||
|
||||
/// Mandatory frame property
|
||||
PropertyParser.cooFrame = function(properties) {
|
||||
let cooFrame = (properties && properties.hips_body && "ICRSd") || (properties && properties.hips_frame) || "ICRS";
|
||||
return cooFrame;
|
||||
PropertyParser.frame = function(options, properties = {}) {
|
||||
let frame = (options && options.cooFrame) || (properties.hips_body && "ICRSd") || properties.hips_frame;
|
||||
|
||||
if (frame == "ICRS" || frame == "ICRSd" || frame == "equatorial" || frame == "j2000") {
|
||||
frame = "ICRS";
|
||||
} else if (frame == "galactic") {
|
||||
frame = "GAL";
|
||||
} else {
|
||||
frame = "ICRS";
|
||||
console.warn('Invalid cooframe given: ' + cooFrame + '. Coordinate systems supported: "ICRS", "ICRSd", "j2000" or "galactic". ICRS is chosen by default');
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
/// Mandatory maxOrder property
|
||||
PropertyParser.maxOrder = function(properties) {
|
||||
let maxOrder = properties && properties.hips_order && (+properties.hips_order);
|
||||
PropertyParser.maxOrder = function(options, properties = {}) {
|
||||
let maxOrder = (options && options.maxOrder) || (properties.hips_order && (+properties.hips_order));
|
||||
return maxOrder;
|
||||
}
|
||||
|
||||
/// Mandatory minOrder property
|
||||
PropertyParser.minOrder = function(properties) {
|
||||
const minOrder = (properties && properties.hips_order_min && (+properties.hips_order_min)) || 0;
|
||||
PropertyParser.minOrder = function(options, properties = {}) {
|
||||
const minOrder = (options && options.minOrder) || (properties.hips_order_min && (+properties.hips_order_min)) || 0;
|
||||
return minOrder;
|
||||
}
|
||||
|
||||
PropertyParser.formats = function(properties) {
|
||||
let formats = properties && properties.hips_tile_format || "jpeg";
|
||||
PropertyParser.formats = function(options, properties = {}) {
|
||||
let formats = properties.hips_tile_format || "jpeg";
|
||||
|
||||
formats = formats.split(' ')
|
||||
.map((fmt) => fmt.toLowerCase());
|
||||
@@ -73,8 +84,8 @@ PropertyParser.formats = function(properties) {
|
||||
return formats;
|
||||
}
|
||||
|
||||
PropertyParser.initialFov = function(properties) {
|
||||
let initialFov = properties && properties.hips_initial_fov && (+properties.hips_initial_fov);
|
||||
PropertyParser.initialFov = function(options, properties = {}) {
|
||||
let initialFov = properties.hips_initial_fov && +properties.hips_initial_fov;
|
||||
|
||||
if (initialFov && initialFov < 0.00002777777) {
|
||||
initialFov = 360;
|
||||
@@ -83,13 +94,13 @@ PropertyParser.initialFov = function(properties) {
|
||||
return initialFov;
|
||||
}
|
||||
|
||||
PropertyParser.skyFraction = function(properties) {
|
||||
const skyFraction = (properties && properties.moc_sky_fraction && (+properties.moc_sky_fraction)) || 0.0;
|
||||
PropertyParser.skyFraction = function(options, properties = {}) {
|
||||
const skyFraction = (properties.moc_sky_fraction && (+properties.moc_sky_fraction)) || 0.0;
|
||||
return skyFraction;
|
||||
}
|
||||
|
||||
PropertyParser.cutouts = function(properties) {
|
||||
let cuts = properties && properties.hips_pixel_cut && properties.hips_pixel_cut.split(" ");
|
||||
PropertyParser.cutouts = function(options, properties = {}) {
|
||||
let cuts = properties.hips_pixel_cut && properties.hips_pixel_cut.split(" ");
|
||||
|
||||
const minCutout = cuts && parseFloat(cuts[0]);
|
||||
const maxCutout = cuts && parseFloat(cuts[1]);
|
||||
@@ -97,32 +108,25 @@ PropertyParser.cutouts = function(properties) {
|
||||
return [minCutout, maxCutout];
|
||||
}
|
||||
|
||||
PropertyParser.bitpix = function(properties) {
|
||||
const bitpix = properties && properties.hips_pixel_bitpix && (+properties.hips_pixel_bitpix);
|
||||
PropertyParser.bitpix = function(options, properties = {}) {
|
||||
const bitpix = properties.hips_pixel_bitpix && (+properties.hips_pixel_bitpix);
|
||||
return bitpix;
|
||||
}
|
||||
|
||||
PropertyParser.dataproductSubtype = function(properties) {
|
||||
let dataproductSubtype = (properties && properties.dataproduct_subtype) || "color";
|
||||
PropertyParser.dataproductSubtype = function(options, properties = {}) {
|
||||
let dataproductSubtype = properties.dataproduct_subtype || "color";
|
||||
dataproductSubtype = dataproductSubtype.split(" ")
|
||||
.map((subtype) => subtype.toLowerCase());
|
||||
return dataproductSubtype;
|
||||
}
|
||||
|
||||
PropertyParser.isPlanetaryBody = function(properties) {
|
||||
return properties && properties.hips_body !== undefined;
|
||||
PropertyParser.isPlanetaryBody = function(options, properties = {}) {
|
||||
return properties.hips_body !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ImageSurveyOptions
|
||||
*
|
||||
* @property {string} [name] - The name of the survey to be displayed in the UI
|
||||
* @property {string} [imgFormat] - Formats accepted 'webp', 'png', 'jpeg' or 'fits'. Will raise an error if the HiPS does not contain tiles in this format
|
||||
* @property {CooFrame} [cooFrame="J2000"] - Coordinate frame of the survey tiles
|
||||
* @property {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
* @property {number} [numBitsPerPixel] - Useful if you want to display the FITS tiles of a HiPS. It specifies the number of bits per pixel. Possible values are:
|
||||
* -64: double, -32: float, 8: unsigned byte, 16: short, 32: integer 32 bits, 64: integer 64 bits
|
||||
* @property {number} [tileSize] - The width of the HEALPix tile images. Mostly 512 pixels but can be 256, 128, 64, 32
|
||||
* @property {number} [opacity=1.0] - Opacity of the survey or image (value between 0 and 1).
|
||||
* @property {string} [colormap="native"] - The colormap configuration for the survey or image.
|
||||
* @property {string} [stretch="linear"] - The stretch configuration for the survey or image.
|
||||
@@ -134,9 +138,12 @@ PropertyParser.isPlanetaryBody = function(properties) {
|
||||
* @property {number} [saturation=0.0] - The saturation value for the color configuration.
|
||||
* @property {number} [brightness=0.0] - The brightness value for the color configuration.
|
||||
* @property {number} [contrast=0.0] - The contrast value for the color configuration.
|
||||
* @property {number} [maxOrder] - If not given, retrieved from the properties of the survey.
|
||||
* @property {number} [minOrder] - If not given, retrieved from the properties of the survey.
|
||||
* @property {boolean} [longitudeReversed=false] - Set it to True for planetary survey visualization
|
||||
*/
|
||||
* @property {string} [imgFormat] - If not given, look into the properties to see the accepted format. The format is chosen from WEBP > PNG > JPEG > FITS (in this importance order).
|
||||
* @property {string} [cooFrame] - If not given, look into the properties. If it is a planet, then ICRS is chosen, otherwise its hips_frame key is read. If no value is found in the properties, ICRS is chosen by default.
|
||||
*/
|
||||
export let ImageSurvey = (function () {
|
||||
/**
|
||||
* The object describing an image survey
|
||||
@@ -144,73 +151,35 @@ export let ImageSurvey = (function () {
|
||||
* @class
|
||||
* @constructs ImageSurvey
|
||||
*
|
||||
* @param {string} id - Mandatory unique identifier for the layer.
|
||||
* Can be an arbitrary name
|
||||
* @param {string} url - Can be an url to the survey or a "CDS" ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}
|
||||
* @param {string} [id] - Optional, a uniq id for the survey. See {@link https://aladin.cds.unistra.fr/hips/list|here} for the list of IDs.
|
||||
* Keep in mind that it is better to directly provide an url as it will not request our mocserver first to get final survey tiles retrieval url.
|
||||
* @param {string} [name] - The name of the survey to be displayed in the UI
|
||||
* @param {string} url - The url where the survey is located. Check the hips list {@link https://aladin.cds.unistra.fr/hips/list|here} for the valid survey urls to display.
|
||||
* @param {ImageSurveyOptions} [options] - The option for the survey
|
||||
*
|
||||
* @description For the `url` param, prefer provide an url better than an CDS ID. Giving a CDS ID will do a query to the mocserver more but will also check for the presence of faster HiPS nodes.
|
||||
* @description Prefer provide an url better than an id. If both are given, the url will be requested first for the survey data.
|
||||
*/
|
||||
function ImageSurvey(id, url, options) {
|
||||
function ImageSurvey(id, name, url, options, view) {
|
||||
this.view = view;
|
||||
this.added = false;
|
||||
// Unique identifier for a survey
|
||||
this.id = id;
|
||||
this.name = options.name || id || url;
|
||||
this.name = name;
|
||||
this.subtype = "survey";
|
||||
|
||||
this.url = url;
|
||||
this.maxOrder = options.maxOrder;
|
||||
this.minOrder = options.minOrder || 0;
|
||||
this.cooFrame = options.cooFrame;
|
||||
this.tileSize = options.tileSize;
|
||||
this.longitudeReversed = options.longitudeReversed === undefined ? false : options.longitudeReversed;
|
||||
this.imgFormat = options.imgFormat;
|
||||
this.numBitsPerPixel = options.numBitsPerPixel;
|
||||
this.creatorDid = options.creatorDid;
|
||||
|
||||
this.properties = options.properties || {};
|
||||
this.colorCfg = new ColorCfg(options);
|
||||
};
|
||||
|
||||
ImageSurvey.prototype.setView = function(view) {
|
||||
let self = this;
|
||||
|
||||
// do not allow to call setView multiple times otherwise
|
||||
// the querying to the properties and the search to the best
|
||||
// HiPS node will be done again for the same imageHiPS
|
||||
if (self.view) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.view = view;
|
||||
|
||||
let isMOCServerToBeQueried = true;
|
||||
if (this.imgFormat === 'fits') {
|
||||
// a fits is given
|
||||
isMOCServerToBeQueried = !(this.maxOrder && this.url && this.imgFormat && this.tileSize && this.cooFrame && this.numBitsPerPixel)
|
||||
} else {
|
||||
isMOCServerToBeQueried = !(this.maxOrder && this.url && this.imgFormat && this.tileSize && this.cooFrame);
|
||||
}
|
||||
|
||||
self.query = (async () => {
|
||||
if (isMOCServerToBeQueried) {
|
||||
let properties;
|
||||
let isCDSId = false;
|
||||
try {
|
||||
properties = await HiPSProperties.fetchFromUrl(self.url)
|
||||
/*.catch((e) => {
|
||||
// try with the proxy
|
||||
url = Utils.handleCORSNotSameOrigin(url).href;
|
||||
if (!options.properties) {
|
||||
let obsTitle, creatorDid, maxOrder, frame, tileSize, formats, minCutout, maxCutout, bitpix, skyFraction, minOrder, initialFov, initialRa, initialDec, hipsBody, isPlanetaryBody, dataproductSubtype;
|
||||
|
||||
return HiPSProperties.fetchFromUrl(url);
|
||||
})*/
|
||||
let properties;
|
||||
try {
|
||||
properties = await HiPSProperties.fetchFromUrl(url)
|
||||
.catch(async (e) => {
|
||||
// url not valid so we try with the id
|
||||
try {
|
||||
isCDSId = true;
|
||||
// the url stores a "CDS ID" we take it prioritaly
|
||||
// if the url is null, take the id, this is for some tests
|
||||
// to pass because some users might just give null as url param and a "CDS ID" as id param
|
||||
let id = self.url || self.id;
|
||||
return await HiPSProperties.fetchFromID(id);
|
||||
} catch(e) {
|
||||
throw e;
|
||||
@@ -220,198 +189,200 @@ export let ImageSurvey = (function () {
|
||||
throw e;
|
||||
}
|
||||
|
||||
//obsTitle = properties.obs_title;
|
||||
self.creatorDid = properties.creator_did || self.creatorDid;
|
||||
// url
|
||||
|
||||
if (isCDSId) {
|
||||
self.url = properties.hips_service_url
|
||||
if (!self.url) {
|
||||
throw 'no valid service URL for retrieving the tiles'
|
||||
}
|
||||
|
||||
self.url = Utils.fixURLForHTTPS(self.url);
|
||||
|
||||
// Request all the properties to see which mirror is the fastest
|
||||
HiPSProperties.getFasterMirrorUrl(properties, self.url)
|
||||
.then((url) => {
|
||||
if (self.url !== url) {
|
||||
console.info("Change url of ", self.id, " from ", self.url, " to ", url)
|
||||
|
||||
// If added to the backend, then we need to tell it the url has changed
|
||||
if (self.added) {
|
||||
self.view.wasm.setHiPSUrl(self.creatorDid, url);
|
||||
}
|
||||
|
||||
self.url = url;
|
||||
|
||||
// save the new url to the cache
|
||||
ImageSurvey.cache[self.id].url = self.url;
|
||||
}
|
||||
})
|
||||
/*.catch(e => {
|
||||
//alert(e);
|
||||
console.error(e);
|
||||
// the survey has been added so we remove it from the stack
|
||||
self.view.removeImageLayer(self.layer)
|
||||
//throw e;
|
||||
})*/
|
||||
obsTitle = properties.obs_title;
|
||||
creatorDid = properties.creator_did;
|
||||
// Set it to a default value
|
||||
if (!properties.hips_service_url) {
|
||||
throw 'no valid service URL for retrieving the tiles'
|
||||
}
|
||||
url = Utils.fixURLForHTTPS(properties.hips_service_url);
|
||||
|
||||
// Request all the properties to see which mirror is the fastest
|
||||
HiPSProperties.getFasterMirrorUrl(properties)
|
||||
.then((url) => {
|
||||
self._setUrl(url);
|
||||
})
|
||||
.catch(e => {
|
||||
//alert(e);
|
||||
console.error(e);
|
||||
// the survey has been added so we remove it from the stack
|
||||
self.view.removeImageLayer(self.layer)
|
||||
//throw e;
|
||||
})
|
||||
|
||||
// Max order
|
||||
self.maxOrder = PropertyParser.maxOrder(properties) || self.maxOrder;
|
||||
maxOrder = PropertyParser.maxOrder(options, properties);
|
||||
|
||||
// Tile size
|
||||
self.tileSize = PropertyParser.tileSize(properties) || self.tileSize;
|
||||
tileSize = PropertyParser.tileSize(options, properties);
|
||||
|
||||
// Tile formats
|
||||
self.formats = PropertyParser.formats(properties) || self.formats;
|
||||
formats = PropertyParser.formats(options, properties);
|
||||
|
||||
// min order
|
||||
self.minOrder = PropertyParser.minOrder(properties) || self.minOrder;
|
||||
minOrder = PropertyParser.minOrder(options, properties);
|
||||
|
||||
// Frame
|
||||
self.cooFrame = PropertyParser.cooFrame(properties) || self.cooFrame;
|
||||
frame = PropertyParser.frame(options, properties);
|
||||
|
||||
// sky fraction
|
||||
self.skyFraction = PropertyParser.skyFraction(properties);
|
||||
skyFraction = PropertyParser.skyFraction(options, properties);
|
||||
|
||||
// Initial fov/ra/dec
|
||||
self.initialFov = PropertyParser.initialFov(properties);
|
||||
self.initialRa = properties && properties.hips_initial_ra && (+properties.hips_initial_ra);
|
||||
self.initialDec = properties && properties.hips_initial_dec && (+properties.hips_initial_dec);
|
||||
initialFov = PropertyParser.initialFov(options, properties);
|
||||
initialRa = +properties.hips_initial_ra;
|
||||
initialDec = +properties.hips_initial_dec;
|
||||
|
||||
// Cutouts
|
||||
const cutoutFromProperties = PropertyParser.cutouts(properties);
|
||||
self.minCut = cutoutFromProperties[0];
|
||||
self.maxCut = cutoutFromProperties[1];
|
||||
[minCutout, maxCutout] = PropertyParser.cutouts(options, properties);
|
||||
|
||||
// Bitpix
|
||||
self.numBitsPerPixel = PropertyParser.bitpix(properties) || self.numBitsPerPixel;
|
||||
bitpix = PropertyParser.bitpix(options, properties);
|
||||
|
||||
// Dataproduct subtype
|
||||
dataproductSubtype = PropertyParser.dataproductSubtype(options, properties);
|
||||
|
||||
// HiPS body
|
||||
isPlanetaryBody = PropertyParser.isPlanetaryBody(options, properties);
|
||||
if (properties.hips_body) {
|
||||
self.hipsBody = properties.hips_body;
|
||||
// Use the property to define and check some user given infos
|
||||
// Longitude reversed
|
||||
self.longitudeReversed = true;
|
||||
hipsBody = properties.hips_body;
|
||||
}
|
||||
|
||||
// Give a better name if we have the HiPS metadata
|
||||
self.name = self.name || properties.obsTitle;
|
||||
|
||||
self.cooFrame = properties.cooFrame || self.cooFrame;
|
||||
self.properties = {
|
||||
creatorDid,
|
||||
obsTitle,
|
||||
url,
|
||||
maxOrder,
|
||||
frame,
|
||||
tileSize,
|
||||
formats,
|
||||
minCutout,
|
||||
maxCutout,
|
||||
bitpix,
|
||||
skyFraction,
|
||||
minOrder,
|
||||
hipsInitialFov: initialFov,
|
||||
hipsInitialRa: initialRa,
|
||||
hipsInitialDec: initialDec,
|
||||
dataproductSubtype,
|
||||
isPlanetaryBody,
|
||||
hipsBody
|
||||
};
|
||||
}
|
||||
|
||||
self.creatorDid = self.creatorDid || self.id || self.url;
|
||||
// Give a better name if we have the HiPS metadata
|
||||
self.name = self.name || self.properties.obsTitle;
|
||||
|
||||
// Use the property to define and check some user given infos
|
||||
// Longitude reversed
|
||||
let longitudeReversed = false;
|
||||
if (options && options.longitudeReversed === true) {
|
||||
longitudeReversed = true;
|
||||
}
|
||||
|
||||
if (self.properties.hipsBody) {
|
||||
longitudeReversed = true;
|
||||
}
|
||||
|
||||
self.longitudeReversed = longitudeReversed;
|
||||
|
||||
// Image format
|
||||
if (self.imgFormat) {
|
||||
let imgFormat = options && options.imgFormat;
|
||||
if (imgFormat) {
|
||||
// transform to lower case
|
||||
self.imgFormat = self.imgFormat.toLowerCase();
|
||||
imgFormat = imgFormat.toLowerCase();
|
||||
// convert JPG -> JPEG
|
||||
if (self.imgFormat === "jpg") {
|
||||
self.imgFormat = "jpeg";
|
||||
if (imgFormat === "jpg") {
|
||||
imgFormat = "jpeg";
|
||||
}
|
||||
|
||||
// user wants a fits but the properties tells this format is not available
|
||||
if (self.imgFormat === "fits" && self.formats && self.formats.indexOf('fits') < 0) {
|
||||
if (imgFormat === "fits" && self.properties.formats && self.properties.formats.indexOf('fits') < 0) {
|
||||
throw self.name + " does not provide fits tiles";
|
||||
}
|
||||
|
||||
if (self.imgFormat === "webp" && self.formats && self.formats.indexOf('webp') < 0) {
|
||||
if (imgFormat === "webp" && self.properties.formats && self.properties.formats.indexOf('webp') < 0) {
|
||||
throw self.name + " does not provide webp tiles";
|
||||
}
|
||||
|
||||
if (self.imgFormat === "png" && self.formats && self.formats.indexOf('png') < 0) {
|
||||
if (imgFormat === "png" && self.properties.formats && self.properties.formats.indexOf('png') < 0) {
|
||||
throw self.name + " does not provide png tiles";
|
||||
}
|
||||
|
||||
if (self.imgFormat === "jpeg" && self.formats && self.formats.indexOf('jpeg') < 0) {
|
||||
if (imgFormat === "jpeg" && self.properties.formats && self.properties.formats.indexOf('jpeg') < 0) {
|
||||
throw self.name + " does not provide jpeg tiles";
|
||||
}
|
||||
} else {
|
||||
// user wants nothing then we choose one from the properties
|
||||
if (self.formats.indexOf('webp') >= 0) {
|
||||
self.imgFormat = "webp";
|
||||
} else if (self.formats.indexOf('png') >= 0) {
|
||||
self.imgFormat = "png";
|
||||
} else if (self.formats.indexOf('jpeg') >= 0) {
|
||||
self.imgFormat = "jpeg";
|
||||
} else if (self.formats.indexOf('fits') >= 0) {
|
||||
self.imgFormat = "fits";
|
||||
if (self.properties.formats.indexOf('webp') >= 0) {
|
||||
imgFormat = "webp";
|
||||
} else if (self.properties.formats.indexOf('png') >= 0) {
|
||||
imgFormat = "png";
|
||||
} else if (self.properties.formats.indexOf('jpeg') >= 0) {
|
||||
imgFormat = "jpeg";
|
||||
} else if (self.properties.formats.indexOf('fits') >= 0) {
|
||||
imgFormat = "fits";
|
||||
} else {
|
||||
throw "Unsupported format(s) found in the properties: " + self.formats;
|
||||
throw "Unsupported format(s) found in the properties: " + self.properties.formats;
|
||||
}
|
||||
}
|
||||
|
||||
// Cutouts
|
||||
self.imgFormat = imgFormat;
|
||||
|
||||
// Initialize the color meta data here
|
||||
let minCut, maxCut;
|
||||
if (self.imgFormat === "fits") {
|
||||
if (imgFormat === "fits") {
|
||||
// Take into account the default cuts given by the property file (this is true especially for FITS HiPSes)
|
||||
minCut = self.colorCfg.minCut || self.minCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || self.maxCut || 1.0;
|
||||
minCut = self.colorCfg.minCut || (options && options.minCut) || self.properties.minCutout || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || (options && options.maxCut) || self.properties.maxCutout || 1.0;
|
||||
} else {
|
||||
minCut = self.colorCfg.minCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || 1.0;
|
||||
minCut = self.colorCfg.minCut || (options && options.minCut) || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || (options && options.maxCut) || 1.0;
|
||||
}
|
||||
self.colorCfg.setCuts(minCut, maxCut);
|
||||
|
||||
// Coo frame
|
||||
if (self.cooFrame == "ICRS" || self.cooFrame == "ICRSd" || self.cooFrame == "equatorial" || self.cooFrame == "j2000") {
|
||||
self.cooFrame = "ICRS";
|
||||
} else if (self.cooFrame == "galactic") {
|
||||
self.cooFrame = "GAL";
|
||||
} else {
|
||||
self.cooFrame = "ICRS";
|
||||
console.warn('Invalid cooframe given: ' + self.cooFrame + '. Coordinate systems supported: "ICRS", "ICRSd", "j2000" or "galactic". ICRS is chosen by default');
|
||||
}
|
||||
|
||||
self.formats = self.formats || [self.imgFormat];
|
||||
|
||||
self._save();
|
||||
ImageLayer.update(self);
|
||||
|
||||
return self;
|
||||
})();
|
||||
};
|
||||
|
||||
ImageSurvey.fromLayerOptions = function(aladin, options) {
|
||||
return new ImageSurvey(
|
||||
options.id,
|
||||
options.name,
|
||||
options.url,
|
||||
{
|
||||
properties: options,
|
||||
...options.options
|
||||
},
|
||||
aladin.view
|
||||
);
|
||||
}
|
||||
|
||||
ImageSurvey.prototype._save = function() {
|
||||
let self = this;
|
||||
ImageSurvey.prototype._setUrl = function (url) {
|
||||
if (this.properties.url !== url) {
|
||||
console.info("Change url of ", this.id, " from ", this.properties.url, " to ", url)
|
||||
|
||||
let surveyOpt = {
|
||||
creatorDid: self.creatorDid,
|
||||
name: self.name,
|
||||
url: self.url,
|
||||
cooFrame: self.cooFrame,
|
||||
maxOrder: self.maxOrder,
|
||||
tileSize: self.tileSize,
|
||||
imgFormat: self.imgFormat,
|
||||
// If added to the backend, then we need to tell it the url has changed
|
||||
if (this.added) {
|
||||
this.view.wasm.setHiPSUrl(this.properties.url, url);
|
||||
}
|
||||
|
||||
this.properties.url = url;
|
||||
}
|
||||
|
||||
if (self.numBitsPerPixel) {
|
||||
surveyOpt.numBitsPerPixel = self.numBitsPerPixel;
|
||||
}
|
||||
|
||||
ImageSurvey.cache[self.id] = {
|
||||
// Erase by the cache already put values which is considered
|
||||
// as the ground truth
|
||||
...ImageSurvey.cache[self.id],
|
||||
// append new important infos from the properties queried
|
||||
...surveyOpt,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Checks if the ImageSurvey represents a planetary body.
|
||||
*
|
||||
* This method returns a boolean indicating whether the ImageSurvey corresponds to a planetary body, e.g. the earth or a celestial body.
|
||||
*
|
||||
* @memberof ImageSurvey
|
||||
*
|
||||
* @returns {boolean} Returns true if the ImageSurvey represents a planetary body; otherwise, returns false.
|
||||
*/
|
||||
* Checks if the ImageSurvey represents a planetary body.
|
||||
*
|
||||
* This method returns a boolean indicating whether the ImageSurvey corresponds to a planetary body, e.g. the earth or a celestial body.
|
||||
*
|
||||
* @memberof ImageSurvey
|
||||
*
|
||||
* @returns {boolean} Returns true if the ImageSurvey represents a planetary body; otherwise, returns false.
|
||||
*/
|
||||
ImageSurvey.prototype.isPlanetaryBody = function() {
|
||||
return this.hipsBody !== undefined;
|
||||
return this.properties.isPlanetaryBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -448,7 +419,7 @@ export let ImageSurvey = (function () {
|
||||
|
||||
// Check the properties to see if the given format is available among the list
|
||||
// If the properties have not been retrieved yet, it will be tested afterwards
|
||||
const availableFormats = self.formats;
|
||||
const availableFormats = self.properties.formats;
|
||||
// user wants a fits but the metadata tells this format is not available
|
||||
if (imgFormat === "fits" && availableFormats.indexOf('fits') < 0) {
|
||||
throw self.id + " does not provide fits tiles";
|
||||
@@ -468,8 +439,8 @@ export let ImageSurvey = (function () {
|
||||
|
||||
// Switch from png/webp/jpeg to fits
|
||||
if ((self.imgFormat === 'png' || self.imgFormat === "webp" || self.imgFormat === "jpeg") && imgFormat === 'fits') {
|
||||
if (self.minCut && self.maxCut) {
|
||||
self.setCuts(self.minCut, self.maxCut)
|
||||
if (self.properties.minCutout && self.properties.maxCutout) {
|
||||
self.setCuts(self.properties.minCutout, self.properties.maxCutout)
|
||||
}
|
||||
// Switch from fits to png/webp/jpeg
|
||||
} else if (self.imgFormat === "fits") {
|
||||
@@ -482,7 +453,7 @@ export let ImageSurvey = (function () {
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Sets the opacity factor when rendering the ImageSurvey
|
||||
*
|
||||
* @memberof ImageSurvey
|
||||
@@ -490,7 +461,7 @@ export let ImageSurvey = (function () {
|
||||
* @returns {string[]} Returns the formats accepted for the survey, i.e. the formats of tiles that are availables. Could be PNG, WEBP, JPG and FITS.
|
||||
*/
|
||||
ImageSurvey.prototype.getAvailableFormats = function() {
|
||||
return this.formats;
|
||||
return this.properties.formats;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,12 +624,14 @@ export let ImageSurvey = (function () {
|
||||
|
||||
// Tell the view its meta have changed
|
||||
try {
|
||||
this.metadata = {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat
|
||||
};
|
||||
|
||||
if (this.added) {
|
||||
this.view.wasm.setImageMetadata(this.layer, {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat
|
||||
});
|
||||
this.view.wasm.setImageMetadata(this.layer, this.metadata);
|
||||
// once the meta have been well parsed, we can set the meta
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(this.view.aladinDiv, { layer: this });
|
||||
}
|
||||
@@ -670,31 +643,17 @@ export let ImageSurvey = (function () {
|
||||
|
||||
ImageSurvey.prototype.add = function (layer) {
|
||||
this.layer = layer;
|
||||
let self = this;
|
||||
|
||||
this.metadata = {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat
|
||||
};
|
||||
|
||||
this.view.wasm.addImageSurvey({
|
||||
layer,
|
||||
properties: {
|
||||
creatorDid: self.creatorDid,
|
||||
url: self.url,
|
||||
maxOrder: self.maxOrder,
|
||||
cooFrame: self.cooFrame,
|
||||
tileSize: self.tileSize,
|
||||
formats: self.formats,
|
||||
bitpix: self.numBitsPerPixel,
|
||||
skyFraction: self.skyFraction,
|
||||
minOrder: self.minOrder,
|
||||
hipsInitialFov: self.initialFov,
|
||||
hipsInitialRa: self.initialRa,
|
||||
hipsInitialDec: self.initialDec,
|
||||
isPlanetaryBody: self.isPlanetaryBody(),
|
||||
hipsBody: self.hipsBody
|
||||
},
|
||||
meta: {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat
|
||||
},
|
||||
properties: this.properties,
|
||||
meta: this.metadata,
|
||||
});
|
||||
|
||||
this.added = true;
|
||||
@@ -737,272 +696,7 @@ export let ImageSurvey = (function () {
|
||||
return this.view.wasm.readPixel(x, y, this.layer);
|
||||
};
|
||||
|
||||
ImageSurvey.DEFAULT_SURVEY_ID = "CDS/P/DSS2/color";
|
||||
|
||||
// A cache storing directly surveys important information to not query for the properties each time
|
||||
ImageSurvey.cache = {
|
||||
DSS2_color: {
|
||||
creatorDid: "ivo://CDS/P/DSS2/color",
|
||||
name: "DSS colored",
|
||||
url: "https://alasky.cds.unistra.fr/DSS/DSSColor",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: "ICRS"
|
||||
},
|
||||
MASS2_color: {
|
||||
creatorDid: "ivo://CDS/P/2MASS/color",
|
||||
name: "2MASS colored",
|
||||
url: "https://alasky.cds.unistra.fr/2MASS/Color",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: "ICRS"
|
||||
},
|
||||
DSS2_red: {
|
||||
creatorDid: "ivo://CDS/P/DSS2/red",
|
||||
name: "DSS2 Red (F+R)",
|
||||
url: "https://alasky.cds.unistra.fr/DSS/DSS2Merged",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: 'fits',
|
||||
cooFrame: "ICRS",
|
||||
numBitsPerPixel: 16,
|
||||
// options
|
||||
minCut: 1000.0,
|
||||
maxCut: 10000.0,
|
||||
colormap: "magma",
|
||||
stretch: 'Linear',
|
||||
imgFormat: "fits"
|
||||
},
|
||||
GAIA_EDR3: {
|
||||
creatorDid: "ivo://CDS/P/DM/I/350/gaiaedr3",
|
||||
name: "Density map for Gaia EDR3 (I/350/gaiaedr3)",
|
||||
url: "https://alasky.cds.unistra.fr/ancillary/GaiaEDR3/density-map",
|
||||
maxOrder: 7,
|
||||
tileSize: 512,
|
||||
numBitsPerPixel: -32,
|
||||
cooFrame: "ICRS",
|
||||
minCut: 0,
|
||||
maxCut: 12000,
|
||||
stretch: 'asinh',
|
||||
colormap: "rdylbu",
|
||||
imgFormat: "fits",
|
||||
},
|
||||
PanSTARRS_DR1_g: {
|
||||
creatorDid: "ivo://CDS/P/PanSTARRS/DR1/g",
|
||||
name: "PanSTARRS DR1 g",
|
||||
url: "https://alasky.cds.unistra.fr/Pan-STARRS/DR1/g",
|
||||
maxOrder: 11,
|
||||
tileSize: 512,
|
||||
imgFormat: 'fits',
|
||||
cooFrame: "ICRS",
|
||||
numBitsPerPixel: -32,
|
||||
// options
|
||||
minCut: -34,
|
||||
maxCut: 7000,
|
||||
stretch: 'asinh',
|
||||
colormap: "redtemperature",
|
||||
},
|
||||
PanSTARRS_DR1_color: {
|
||||
creatorDid: "ivo://CDS/P/PanSTARRS/DR1/color-z-zg-g",
|
||||
name: "PanSTARRS DR1 color",
|
||||
url: "https://alasky.cds.unistra.fr/Pan-STARRS/DR1/color-z-zg-g",
|
||||
maxOrder: 11,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: "ICRS",
|
||||
},
|
||||
DECaPS_DR2_color: {
|
||||
creatorDid: "ivo://CDS/P/DECaPS/DR2/color",
|
||||
name: "DECaPS DR2 color",
|
||||
url: "https://alasky.cds.unistra.fr/DECaPS/DR2/CDS_P_DECaPS_DR2_color/",
|
||||
maxOrder: 11,
|
||||
cooFrame: "equatorial",
|
||||
tileSize: 512,
|
||||
imgFormat: 'png',
|
||||
},
|
||||
Fermi_color: {
|
||||
creatorDid: "ivo://CDS/P/Fermi/color",
|
||||
name: "Fermi color",
|
||||
url: "https://alasky.cds.unistra.fr/Fermi/Color",
|
||||
maxOrder: 3,
|
||||
imgFormat: 'jpeg',
|
||||
tileSize: 512,
|
||||
cooFrame: 'equatorial'
|
||||
},
|
||||
Galex_NUV: {
|
||||
creatorDid: "ivo://CDS/P/GALEXGR6_7/NUV",
|
||||
id: "P/GALEXGR6_7/NUV",
|
||||
name: "GALEXGR6_7 NUV",
|
||||
url: "http://alasky.cds.unistra.fr/GALEX/GALEXGR6_7_NUV/",
|
||||
maxOrder: 8,
|
||||
imgFormat: 'png',
|
||||
tileSize: 512,
|
||||
cooFrame: 'equatorial'
|
||||
},
|
||||
IRIS_color: {
|
||||
creatorDid: "ivo://CDS/P/IRIS/color",
|
||||
id: "P/IRIS/color",
|
||||
name: "IRIS colored",
|
||||
url: "https://alasky.cds.unistra.fr/IRISColor",
|
||||
maxOrder: 3,
|
||||
tileSize: 256,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: 'galactic'
|
||||
},
|
||||
Mellinger_color: {
|
||||
creatorDid: "ivo://CDS/P/Mellinger/color",
|
||||
id: "P/Mellinger/color",
|
||||
name: "Mellinger colored",
|
||||
url: "https://alasky.cds.unistra.fr/MellingerRGB",
|
||||
maxOrder: 4,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: 'galactic'
|
||||
},
|
||||
SDSS9_color: {
|
||||
creatorDid: "ivo://CDS/P/SDSS9/color",
|
||||
id: "P/SDSS9/color",
|
||||
name: "SDSS9 colored",
|
||||
url: "https://alasky.cds.unistra.fr/SDSS/DR9/color",
|
||||
maxOrder: 10,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: 'equatorial'
|
||||
},
|
||||
SPITZER_color: {
|
||||
creatorDid: "ivo://CDS/P/SPITZER/color",
|
||||
id: "P/SPITZER/color",
|
||||
name: "IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)",
|
||||
url: "http://alasky.cds.unistra.fr/Spitzer/SpitzerI1I2I4color/",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: 'galactic'
|
||||
},
|
||||
allWISE_color: {
|
||||
creatorDid: "ivo://CDS/P/allWISE/color",
|
||||
id: "P/allWISE/color",
|
||||
name: "AllWISE color",
|
||||
url: "https://alasky.cds.unistra.fr/AllWISE/RGB-W4-W2-W1/",
|
||||
maxOrder: 8,
|
||||
tileSize: 512,
|
||||
imgFormat: 'jpeg',
|
||||
cooFrame: 'equatorial'
|
||||
},
|
||||
/*SDSS9_g: {
|
||||
creatorDid: "ivo://CDS/P/SDSS9/g",
|
||||
id: "P/SDSS9/g",
|
||||
name: "SDSS9 band-g",
|
||||
url: "https://alasky.cds.unistra.fr/SDSS/DR9/band-g",
|
||||
maxOrder: 10,
|
||||
tileSize: 512,
|
||||
numBitsPerPixel: 16,
|
||||
imgFormat: 'fits',
|
||||
cooFrame: 'equatorial',
|
||||
minCut: 0,
|
||||
maxCut: 1.8,
|
||||
stretch: 'linear',
|
||||
colormap: "redtemperature",
|
||||
}*/
|
||||
/*
|
||||
{
|
||||
id: "P/Finkbeiner",
|
||||
name: "Halpha",
|
||||
url: "https://alasky.cds.unistra.fr/FinkbeinerHalpha",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
// options
|
||||
options: {
|
||||
minCut: -10,
|
||||
maxCut: 800,
|
||||
colormap: "rdbu",
|
||||
imgFormat: "fits",
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
id: "P/IRIS/color",
|
||||
name: "IRIS colored",
|
||||
url: "https://alasky.cds.unistra.fr/IRISColor",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/Mellinger/color",
|
||||
name: "Mellinger colored",
|
||||
url: "https://alasky.cds.unistra.fr/MellingerRGB",
|
||||
maxOrder: 4,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/SDSS9/color",
|
||||
name: "SDSS9 colored",
|
||||
url: "https://alasky.cds.unistra.fr/SDSS/DR9/color",
|
||||
maxOrder: 10,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/SDSS9/g",
|
||||
name: "SDSS9 band-g",
|
||||
url: "https://alasky.cds.unistra.fr/SDSS/DR9/band-g",
|
||||
maxOrder: 10,
|
||||
subtype: "survey",
|
||||
options: {
|
||||
stretch: 'asinh',
|
||||
colormap: "redtemperature",
|
||||
imgFormat: 'fits'
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "P/SPITZER/color",
|
||||
name: "IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)",
|
||||
url: "http://alasky.cds.unistra.fr/Spitzer/SpitzerI1I2I4color/",
|
||||
maxOrder: 9,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/VTSS/Ha",
|
||||
name: "VTSS-Ha",
|
||||
url: "https://alasky.cds.unistra.fr/VTSS/Ha",
|
||||
maxOrder: 3,
|
||||
subtype: "survey",
|
||||
options: {
|
||||
minCut: -10.0,
|
||||
maxCut: 100.0,
|
||||
colormap: "grayscale",
|
||||
imgFormat: "fits"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "xcatdb/P/XMM/PN/color",
|
||||
name: "XMM PN colored",
|
||||
url: "https://alasky.cds.unistra.fr/cgi/JSONProxy?url=https://saada.unistra.fr/PNColor",
|
||||
maxOrder: 7,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/allWISE/color",
|
||||
name: "AllWISE color",
|
||||
url: "https://alasky.cds.unistra.fr/AllWISE/RGB-W4-W2-W1/",
|
||||
maxOrder: 8,
|
||||
subtype: "survey",
|
||||
},
|
||||
{
|
||||
id: "P/GLIMPSE360",
|
||||
name: "GLIMPSE360",
|
||||
// This domain is not giving the CORS headers
|
||||
// We need to query by with a proxy equipped with CORS header.
|
||||
url: "https://alasky.cds.unistra.fr/cgi/JSONProxy?url=https://www.spitzer.caltech.edu/glimpse360/aladin/data",
|
||||
subtype: "survey",
|
||||
options: {
|
||||
maxOrder: 9,
|
||||
imgFormat: "jpg",
|
||||
minOrder: 3,
|
||||
}
|
||||
},*/
|
||||
};
|
||||
ImageSurvey.DEFAULT_SURVEY_ID = "P/DSS2/color";
|
||||
|
||||
return ImageSurvey;
|
||||
})();
|
||||
|
||||
@@ -81,6 +81,11 @@ export let MeasurementTable = (function() {
|
||||
this.table = new Tabs({
|
||||
aladin: this.aladin,
|
||||
layout,
|
||||
cssStyle: {
|
||||
position: 'absolute',
|
||||
bottom: '2.4rem',
|
||||
maxWidth: '100%',
|
||||
}
|
||||
}, this.aladin.aladinDiv);
|
||||
};
|
||||
|
||||
|
||||
@@ -103,19 +103,12 @@ export let PlanetaryFeaturesPointer = (function() {
|
||||
|
||||
const featureFieldIdx = fields.findIndex((element) => element.includes('feature_name'));
|
||||
const featureName = values[featureFieldIdx];
|
||||
const featureId = values[fields.indexOf('feature_id')];
|
||||
let moreInfoURL = 'https://planetarynames.wr.usgs.gov/Feature/' + featureId;
|
||||
if (body === 'earth') {
|
||||
const placeId = values[fields.indexOf('place_id')];
|
||||
moreInfoURL = 'https://nominatim.openstreetmap.org/ui/details.html?place_id=' + placeId;
|
||||
}
|
||||
|
||||
const title = '<div class="aladin-sp-title"><a target="_blank" href=" ' + moreInfoURL + '">' + featureName + '</a></div>';
|
||||
const featureId = values[fields.indexOf('feature_id')]
|
||||
const title = '<div class="aladin-sp-title"><a target="_blank" href="https://planetarynames.wr.usgs.gov/Feature/' + featureId + '">' + featureName + '</a></div>';
|
||||
const featureType = values[fields.indexOf('feature_type')]
|
||||
let content = '<div class="aladin-sp-content">' + ' ' + '</div>';
|
||||
content += '<em>Type: </em>' + featureType + '<br><br>';
|
||||
|
||||
content += '<a target="_blank" href="' + moreInfoURL + '">More information</a>';
|
||||
content += '<a target="_blank" href="https://planetarynames.wr.usgs.gov/Feature/' + featureId + '">More information</a>';
|
||||
|
||||
let lon = parseFloat(values[lonFieldIdx]);
|
||||
const lat = parseFloat(values[latFieldIdx]);
|
||||
|
||||
@@ -43,16 +43,16 @@ import { ProjectionEnum } from "./ProjectionEnum.js";
|
||||
export let Polyline= (function() {
|
||||
function _calculateMag2ForNoSinProjections(line, view) {
|
||||
// check if the line is too big (in the clip space) to be drawn
|
||||
const [x1, y1] = view.wasm.screenToClip(line.x1, line.y1);
|
||||
const [x2, y2] = view.wasm.screenToClip(line.x2, line.y2);
|
||||
const [x1, y1] = AladinUtils.viewXyToClipXy(line.x1, line.y1, view.aladin);
|
||||
const [x2, y2] = AladinUtils.viewXyToClipXy(line.x2, line.y2, view.aladin);
|
||||
|
||||
const mag2 = (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2);
|
||||
return mag2;
|
||||
}
|
||||
|
||||
function _isAcrossCollignonZoneForHpxProjection(line, view) {
|
||||
const [x1, y1] = view.wasm.screenToClip(line.x1, line.y1);
|
||||
const [x2, y2] = view.wasm.screenToClip(line.x2, line.y2);
|
||||
const [x1, y1] = AladinUtils.viewXyToClipXy(line.x1, line.y1, view.aladin);
|
||||
const [x2, y2] = AladinUtils.viewXyToClipXy(line.x2, line.y2, view.aladin);
|
||||
|
||||
// x, y, between -1 and 1
|
||||
let triIdxCollignionZone = function(x, y) {
|
||||
@@ -83,8 +83,6 @@ export let Polyline= (function() {
|
||||
this.fillColor = options['fillColor'] || undefined;
|
||||
this.opacity = options['opacity'] || undefined;
|
||||
this.lineWidth = options["lineWidth"] || undefined;
|
||||
this.selectionColor = options["selectionColor"] || '#00ff00';
|
||||
this.hoverColor = options["hoverColor"] || undefined;
|
||||
|
||||
if (options["closed"]) {
|
||||
this.closed = options["closed"];
|
||||
@@ -100,7 +98,8 @@ export let Polyline= (function() {
|
||||
|
||||
this.isShowing = true;
|
||||
this.isSelected = false;
|
||||
this.isHovered = false;
|
||||
|
||||
this.selectionColor = '#00ff00';
|
||||
};
|
||||
|
||||
Polyline.prototype.setOverlay = function(overlay) {
|
||||
@@ -147,26 +146,6 @@ export let Polyline= (function() {
|
||||
}
|
||||
};
|
||||
|
||||
Polyline.prototype.hover = function() {
|
||||
if (this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = true;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
};
|
||||
|
||||
Polyline.prototype.unhover = function() {
|
||||
if (! this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = false;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
};
|
||||
|
||||
Polyline.prototype.getLineWidth = function() {
|
||||
return this.lineWidth;
|
||||
};
|
||||
@@ -202,16 +181,6 @@ export let Polyline= (function() {
|
||||
}
|
||||
};
|
||||
|
||||
Polyline.prototype.setHoverColor = function(color) {
|
||||
if (this.hoverColor == color) {
|
||||
return;
|
||||
}
|
||||
this.hoverColor = color;
|
||||
if (this.overlay) {
|
||||
this.overlay.reportChange();
|
||||
}
|
||||
};
|
||||
|
||||
Polyline.prototype.isFootprint = function() {
|
||||
// The polyline is a footprint if it describes a polygon (i.e. a closed polyline)
|
||||
return this.closed;
|
||||
@@ -246,10 +215,9 @@ export let Polyline= (function() {
|
||||
} else {
|
||||
ctx.strokeStyle = Overlay.increaseBrightness(baseColor, 50);
|
||||
}
|
||||
} else if (this.isHovered) {
|
||||
ctx.strokeStyle = this.hoverColor || Overlay.increaseBrightness(baseColor, 25);
|
||||
} else {
|
||||
ctx.strokeStyle = baseColor;
|
||||
}
|
||||
else {
|
||||
ctx.strokeStyle= baseColor;
|
||||
}
|
||||
|
||||
// 1. project the vertices into the screen
|
||||
|
||||
@@ -90,7 +90,6 @@ export let Popup = (function() {
|
||||
}
|
||||
source.popup = this;
|
||||
this.source = source;
|
||||
|
||||
this.setPosition(source.x, source.y);
|
||||
};
|
||||
|
||||
|
||||
@@ -65,8 +65,6 @@ export let ProgressiveCat = (function() {
|
||||
this.sourceSize = options.sourceSize || 6;
|
||||
this.selectSize = this.sourceSize + 2;
|
||||
this.selectionColor = '#00ff00'; // TODO: to be merged with Catalog
|
||||
this.hoverColor = options.hoverColor || this.color;
|
||||
|
||||
|
||||
// allows for filtering of sources
|
||||
this.filterFn = options.filter || undefined; // TODO: do the same for catalog
|
||||
|
||||
@@ -29,26 +29,25 @@
|
||||
*****************************************************************************/
|
||||
export let ProjectionEnum = {
|
||||
// Zenithal
|
||||
TAN: {id: 1, fov: 150, label: "Tangential"}, /* Gnomonic projection */
|
||||
STG: {id: 2, fov: 360, label: "Stereographic"}, /* Stereographic projection */
|
||||
SIN: {id: 3, fov: 180, 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 */
|
||||
TAN: {id: 1, fov: 150, label: "gnomonic"}, /* Gnomonic projection */
|
||||
STG: {id: 2, fov: 360, label: "stereographic"}, /* Stereographic projection */
|
||||
SIN: {id: 3, fov: 180, label: "orthographic"}, /* Orthographic */
|
||||
ZEA: {id: 4, fov: 360, label: "zenital equal-area"}, /* Equal-area */
|
||||
//FEYE: {id: 5, fov: 190, label: "fish eye"},
|
||||
//AIR: {id: 6, fov: 360, label: "airy"},
|
||||
//AZP: {fov: 180},
|
||||
//ARC: {id: 7, fov: 360, label: "zenital equidistant"},
|
||||
//NCP: {id: 8, fov: 180, label: "north celestial pole"},
|
||||
// Cylindrical
|
||||
MER: {id: 9, fov: 360, label: "Mercator"},
|
||||
MER: {id: 9, fov: 360, label: "mercator"},
|
||||
//CAR: {id: 10, fov: 360, label: "plate carrée"},
|
||||
//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: 360, label: "hammer-aitoff"},
|
||||
//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: 360, label: "mollweide"},
|
||||
// Conic
|
||||
//COD: {id: 17, fov: 360, label: "conic equidistant"},
|
||||
// Hybrid
|
||||
|
||||
@@ -92,10 +92,12 @@ export class Selector {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var objList = [];
|
||||
var cat, sources, s;
|
||||
var footprints, f;
|
||||
var objListPerCatalog = [];
|
||||
|
||||
if (view.catalogs) {
|
||||
for (var k = 0; k < view.catalogs.length; k++) {
|
||||
cat = view.catalogs[k];
|
||||
|
||||
@@ -46,7 +46,6 @@ export let Source = (function() {
|
||||
|
||||
this.isShowing = true;
|
||||
this.isSelected = false;
|
||||
this.isHovered = false;
|
||||
};
|
||||
|
||||
Source.prototype.setCatalog = function(catalog) {
|
||||
@@ -97,26 +96,6 @@ export let Source = (function() {
|
||||
}
|
||||
};
|
||||
|
||||
Source.prototype.hover = function() {
|
||||
if (this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = true;
|
||||
if (this.catalog) {
|
||||
this.catalog.reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
Source.prototype.unhover = function() {
|
||||
if (! this.isHovered) {
|
||||
return;
|
||||
}
|
||||
this.isHovered = false;
|
||||
if (this.catalog) {
|
||||
this.catalog.reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
// function called when a source is clicked. Called by the View object
|
||||
Source.prototype.actionClicked = function(obj) {
|
||||
if (this.catalog && this.catalog.onClick) {
|
||||
|
||||
@@ -40,10 +40,6 @@ export let URLBuilder = (function() {
|
||||
url += '&MAXREC=' + options.limit;
|
||||
}
|
||||
|
||||
if (options && options.verbosity) {
|
||||
url += '&VERB=' + options.verbosity;
|
||||
}
|
||||
|
||||
const orderBy = options && options.orderBy || 'nb_ref';
|
||||
url += '&ORDER_BY=' + orderBy;
|
||||
|
||||
|
||||
180
src/js/View.js
180
src/js/View.js
@@ -50,8 +50,10 @@ import { ObsCore } from "./vo/ObsCore.js";
|
||||
import { DefaultActionsForContextMenu } from "./DefaultActionsForContextMenu.js";
|
||||
import { Layout } from "./gui/Layout.js";
|
||||
import { SAMPActionButton } from "./gui/Button/SAMP.js";
|
||||
import { Icon } from "./gui/Widgets/Icon.js";
|
||||
import openerIconUrl from '../../assets/icons/loading.svg'
|
||||
import { ImageSurvey } from "./ImageSurvey.js";
|
||||
import { ImageFITS } from "./ImageFITS.js";
|
||||
import { ImageLayer } from "./ImageLayer.js";
|
||||
|
||||
export let View = (function () {
|
||||
|
||||
@@ -63,6 +65,8 @@ export let View = (function () {
|
||||
this.aladinDiv = this.aladin.aladinDiv;
|
||||
this.createCanvases();
|
||||
|
||||
this.loadingState = false;
|
||||
|
||||
let self = this;
|
||||
|
||||
self.redrawClbk = this.redraw.bind(this);
|
||||
@@ -80,6 +84,9 @@ export let View = (function () {
|
||||
|
||||
callback(self.wasm);
|
||||
});
|
||||
|
||||
// Retrieve all the possible colormaps
|
||||
ColorCfg.COLORMAPS = this.wasm.getAvailableColormapList();
|
||||
} catch (e) {
|
||||
// For browsers not supporting WebGL2:
|
||||
// 1. Print the original exception message in the console
|
||||
@@ -121,6 +128,7 @@ export let View = (function () {
|
||||
|
||||
this.aladinDiv.ondragover = Utils.dragOverHandler;
|
||||
|
||||
//this.location = location;
|
||||
this.mustClearCatalog = true;
|
||||
this.mode = View.PAN;
|
||||
|
||||
@@ -131,8 +139,18 @@ export let View = (function () {
|
||||
|
||||
var lon, lat;
|
||||
lon = lat = 0;
|
||||
this.projection = ProjectionEnum.SIN;
|
||||
|
||||
// FoV init settings
|
||||
this.viewCenter = { lon: lon, lat: lat }; // position of center of view
|
||||
|
||||
this.cooFrame = CooFrameEnum.fromString(this.options.cooFrame, CooFrameEnum.J2000);
|
||||
|
||||
// Frame setting
|
||||
this.changeFrame(this.cooFrame);
|
||||
|
||||
this.selector = new Selector(this);
|
||||
|
||||
// Zoom starting setting
|
||||
const si = 500000.0;
|
||||
const alpha = 40.0;
|
||||
let initialFov = this.options.fov || 180.0;
|
||||
@@ -142,23 +160,7 @@ export let View = (function () {
|
||||
initialDistance: undefined,
|
||||
initialAccDelta: Math.pow(si / initialFov, 1.0 / alpha)
|
||||
};
|
||||
|
||||
// Projection definition
|
||||
const projName = (this.options && this.options.projection) || "SIN";
|
||||
this.setProjection(projName)
|
||||
|
||||
// Then set the zoom properly once the projection is defined
|
||||
this.setZoom(initialFov);
|
||||
|
||||
// Target position settings
|
||||
this.viewCenter = { lon, lat }; // position of center of view
|
||||
|
||||
// Coo frame setting
|
||||
const cooFrame = CooFrameEnum.fromString(this.options.cooFrame, CooFrameEnum.J2000);
|
||||
this.changeFrame(cooFrame);
|
||||
|
||||
this.selector = new Selector(this);
|
||||
|
||||
// current reference image survey displayed
|
||||
this.imageLayers = new Map();
|
||||
|
||||
@@ -195,6 +197,7 @@ export let View = (function () {
|
||||
|
||||
this.empty = true;
|
||||
|
||||
//this.fixLayoutDimensions();
|
||||
this.promises = [];
|
||||
this.firstHiPS = true;
|
||||
this.curNorder = 1;
|
||||
@@ -228,18 +231,19 @@ export let View = (function () {
|
||||
self.fixLayoutDimensions();
|
||||
})
|
||||
} else {*/
|
||||
let resizeLayout = () => {
|
||||
self.fixLayoutDimensions();
|
||||
}
|
||||
let resizeLayout = () => {
|
||||
self.fixLayoutDimensions();
|
||||
}
|
||||
let doit;
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
clearTimeout(doit);
|
||||
doit = setTimeout(resizeLayout, 100);
|
||||
});
|
||||
|
||||
let doit;
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
//clearTimeout(doit);
|
||||
//doit = setTimeout(resizeLayout, 100);
|
||||
resizeLayout();
|
||||
});
|
||||
self.resizeObserver.observe(this.aladinDiv);
|
||||
//}
|
||||
|
||||
self.resizeObserver.observe(this.aladinDiv)
|
||||
/**/
|
||||
|
||||
this.throttledPositionChanged = Utils.throttle(
|
||||
() => {
|
||||
@@ -346,14 +350,11 @@ export let View = (function () {
|
||||
// called at startup and when window is resized
|
||||
// The WebGL backend is resized
|
||||
View.prototype.fixLayoutDimensions = function () {
|
||||
// make de line height at 0. This prevents the resize observer to infinitely
|
||||
// trigger over and over.
|
||||
this.aladinDiv.style.setProperty('line-height', 0);
|
||||
Utils.cssScale = undefined;
|
||||
|
||||
var computedWidth = Math.floor(parseFloat(this.aladinDiv.getBoundingClientRect().width)) || 1.0;
|
||||
var computedHeight = Math.floor(parseFloat(this.aladinDiv.getBoundingClientRect().height)) || 1.0;
|
||||
|
||||
var computedWidth = parseFloat(window.getComputedStyle(this.aladinDiv).width) || 1.0;
|
||||
var computedHeight = parseFloat(window.getComputedStyle(this.aladinDiv).height) || 1.0;
|
||||
|
||||
this.width = Math.max(computedWidth, 1);
|
||||
this.height = Math.max(computedHeight, 1); // this prevents many problems when div size is equal to 0
|
||||
|
||||
@@ -367,6 +368,10 @@ export let View = (function () {
|
||||
this.mouseMoveIncrement = 160 / this.largestDim;
|
||||
|
||||
// reinitialize 2D context
|
||||
this.imageCtx = this.imageCanvas.getContext("webgl2");
|
||||
//this.aladinDiv.style.width = this.width + "px";
|
||||
//this.aladinDiv.style.height = this.height + "px";
|
||||
this.wasm.resize(this.width, this.height);
|
||||
|
||||
this.catalogCtx = this.catalogCanvas.getContext("2d");
|
||||
this.catalogCtx.canvas.width = this.width;
|
||||
@@ -376,11 +381,6 @@ export let View = (function () {
|
||||
this.gridCtx.canvas.width = this.width;
|
||||
this.gridCtx.canvas.height = this.height;
|
||||
|
||||
this.imageCtx = this.imageCanvas.getContext("webgl2");
|
||||
this.imageCtx.canvas.style.width = this.width + "px";
|
||||
this.imageCtx.canvas.style.height = this.height + "px";
|
||||
this.wasm.resize(this.width, this.height);
|
||||
|
||||
pixelateCanvasContext(this.imageCtx, this.aladin.options.pixelateCanvas);
|
||||
|
||||
// change logo
|
||||
@@ -402,8 +402,6 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
this.computeNorder();
|
||||
|
||||
this.aladinDiv.style.removeProperty('line-height');
|
||||
};
|
||||
|
||||
var pixelateCanvasContext = function (ctx, pixelateFlag) {
|
||||
@@ -633,9 +631,13 @@ export let View = (function () {
|
||||
// Take as start cut values what is inside the properties
|
||||
// If the cuts are not defined in the metadata of the survey
|
||||
// then we take what has been defined by the user
|
||||
cutMinInit = imageLayer.getColorCfg().minCut || 0.0;
|
||||
cutMaxInit = imageLayer.getColorCfg().maxCut || 1.0;
|
||||
|
||||
if (imageLayer.imgFormat === "fits") {
|
||||
cutMinInit = imageLayer.properties.minCutout || imageLayer.getColorCfg().minCut || 0.0;
|
||||
cutMaxInit = imageLayer.properties.maxCutout || imageLayer.getColorCfg().maxCut || 1.0;
|
||||
} else {
|
||||
cutMinInit = imageLayer.getColorCfg().minCut || 0.0;
|
||||
cutMaxInit = imageLayer.getColorCfg().maxCut || 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,6 +811,8 @@ export let View = (function () {
|
||||
if (view.mode == View.TOOL_SIMBAD_POINTER) {
|
||||
// call Simbad pointer or Planetary features
|
||||
GenericPointer(view, e);
|
||||
// exit the simbad pointer mode
|
||||
//view.setMode(View.PAN);
|
||||
|
||||
return; // when in TOOL_SIMBAD_POINTER mode, we do not call the listeners
|
||||
}
|
||||
@@ -989,32 +993,22 @@ export let View = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
if (lastHoveredObject && o != lastHoveredObject) {
|
||||
lastHoveredObject.unhover();
|
||||
|
||||
var objHoveredStopFunction = view.aladin.callbacksByEventName['objectHoveredStop'];
|
||||
|
||||
if (typeof objHoveredStopFunction === 'function') {
|
||||
objHoveredStopFunction(lastHoveredObject, xymouse);
|
||||
}
|
||||
}
|
||||
|
||||
if (o != lastHoveredObject) {
|
||||
o.hover();
|
||||
}
|
||||
lastHoveredObject = o;
|
||||
} else {
|
||||
view.setCursor('default');
|
||||
var objHoveredStopFunction = view.aladin.callbacksByEventName['objectHoveredStop'];
|
||||
if (lastHoveredObject) {
|
||||
// Redraw the scene if the lastHoveredObject is a footprint (e.g. circle or polygon)
|
||||
//if (lastHoveredObject.isFootprint()) {
|
||||
// view.requestRedraw();
|
||||
//}
|
||||
|
||||
if (typeof objHoveredStopFunction === 'function') {
|
||||
// call callback function to notify we left the hovered object
|
||||
var ret = objHoveredStopFunction(lastHoveredObject, xymouse);
|
||||
}
|
||||
|
||||
lastHoveredObject.unhover();
|
||||
}
|
||||
|
||||
|
||||
lastHoveredObject = null;
|
||||
}
|
||||
|
||||
@@ -1359,7 +1353,6 @@ export let View = (function () {
|
||||
this.selection = Selector.getObjects(selection, this);
|
||||
}
|
||||
|
||||
|
||||
if (this.selection.length > 0) {
|
||||
this.selection.forEach((objListPerCatalog) => {
|
||||
objListPerCatalog.forEach((obj) => obj.select())
|
||||
@@ -1416,24 +1409,10 @@ export let View = (function () {
|
||||
|
||||
// Called for touchmove events
|
||||
// initialAccDelta must be consistent with fovDegrees here
|
||||
View.prototype.setZoom = function (fov) {
|
||||
// limit the fov in function of the projection
|
||||
fov = Math.min(fov, this.projection.fov);
|
||||
|
||||
// then clamp the fov between minFov and maxFov
|
||||
const minFoV = this.minFoV;
|
||||
const maxFoV = this.maxFoV;
|
||||
|
||||
if (minFoV) {
|
||||
fov = Math.max(fov, minFoV);
|
||||
}
|
||||
|
||||
if (maxFoV) {
|
||||
fov = Math.min(fov, maxFoV);
|
||||
}
|
||||
|
||||
this.wasm.setFieldOfView(fov);
|
||||
View.prototype.setZoom = function (fovDegrees) {
|
||||
fovDegrees = Math.min(fovDegrees, this.projection.fov);
|
||||
|
||||
this.wasm.setFieldOfView(fovDegrees);
|
||||
this.updateZoomState();
|
||||
};
|
||||
|
||||
@@ -1542,10 +1521,6 @@ export let View = (function () {
|
||||
};
|
||||
|
||||
View.prototype.setOverlayImageLayer = function (imageLayer, layer = "overlay") {
|
||||
// set the view to the image layer object
|
||||
// do the properties query if needed
|
||||
imageLayer.setView(this);
|
||||
|
||||
// register its promise
|
||||
this.imageLayersBeingQueried.set(layer, imageLayer);
|
||||
|
||||
@@ -1559,12 +1534,20 @@ export let View = (function () {
|
||||
// Check whether this layer already exist
|
||||
const idxOverlayLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == layerName);
|
||||
if (idxOverlayLayer == -1) {
|
||||
// it does not exist so we add it to the stack
|
||||
this.overlayLayers.push(layerName);
|
||||
}
|
||||
|
||||
this.imageLayers.set(layerName, imageLayer);
|
||||
// Find the toppest layer
|
||||
//const toppestLayer = this.overlayLayers[this.overlayLayers.length - 1];
|
||||
//this.selectedLayer = toppestLayer;
|
||||
|
||||
// Remove the existant layer if there is one
|
||||
let existantImageLayer = this.imageLayers.get(layerName);
|
||||
if (existantImageLayer) {
|
||||
existantImageLayer.added = false;
|
||||
}
|
||||
|
||||
this.imageLayers.set(layerName, imageLayer);
|
||||
ALEvent.HIPS_LAYER_ADDED.dispatchedTo(this.aladinDiv, { layer: imageLayer });
|
||||
}
|
||||
|
||||
@@ -1587,6 +1570,9 @@ export let View = (function () {
|
||||
.then((imageLayer) => {
|
||||
// Add to the backend
|
||||
const promise = imageLayer.add(layer);
|
||||
|
||||
self.loadingState = true;
|
||||
|
||||
ALEvent.FETCH.dispatchedTo(document, {task});
|
||||
|
||||
return promise;
|
||||
@@ -1604,21 +1590,18 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
// change the view frame in case we have a planetary hips loaded
|
||||
if (imageLayer.hipsBody) {
|
||||
if (imageLayer.properties.hipsBody) {
|
||||
if (this.options.showFrame) {
|
||||
this.aladin.setFrame('J2000d');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
// remove it from the cache
|
||||
delete ImageSurvey.cache[imageLayer.id]
|
||||
delete ImageFITS.cache[imageLayer.id]
|
||||
|
||||
throw e;
|
||||
})
|
||||
.finally(() => {
|
||||
// Loading state is over
|
||||
self.loadingState = false;
|
||||
ALEvent.RESOURCE_FETCHED.dispatchedTo(document, {task});
|
||||
|
||||
self.imageLayersBeingQueried.delete(layer);
|
||||
@@ -1632,7 +1615,9 @@ export let View = (function () {
|
||||
if (noMoreLayersToWaitFor) {
|
||||
if (self.empty) {
|
||||
// no promises to launch!
|
||||
//self.aladin.setBaseImageLayer(self.aladin.createImageSurvey(ImageSurvey.DEFAULT_SURVEY_ID));
|
||||
const dssLayerOptions = ImageLayer.DEFAULT_SURVEY
|
||||
|
||||
self.aladin.setBaseImageLayer(ImageSurvey.fromLayerOptions(self, dssLayerOptions));
|
||||
} else {
|
||||
// there is surveys that have been queried
|
||||
// rename the first overlay layer to "base"
|
||||
@@ -1701,8 +1686,6 @@ export let View = (function () {
|
||||
|
||||
// Get the survey to remove to dissociate it from the view
|
||||
imageLayer.added = false;
|
||||
// Delete it
|
||||
this.imageLayers.delete(layer);
|
||||
|
||||
const idxOverlaidLayer = this.overlayLayers.findIndex(overlaidLayer => overlaidLayer == layer);
|
||||
if (idxOverlaidLayer == -1) {
|
||||
@@ -1710,13 +1693,17 @@ export let View = (function () {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete it
|
||||
this.imageLayers.delete(layer);
|
||||
|
||||
// Remove it from the layer stack
|
||||
this.overlayLayers.splice(idxOverlaidLayer, 1);
|
||||
|
||||
if (this.overlayLayers.length === 0) {
|
||||
this.empty = true;
|
||||
} else if (this.selectedLayer === layer) {
|
||||
// If the layer removed was selected then we select the base layer
|
||||
// find the toppest layer
|
||||
//const toppestLayer = this.overlayLayers[this.overlayLayers.length - 1];
|
||||
this.selectedLayer = 'base';
|
||||
}
|
||||
|
||||
@@ -1726,8 +1713,9 @@ export let View = (function () {
|
||||
const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
if (noMoreLayersToWaitFor && this.empty) {
|
||||
// no promises to launch!
|
||||
const dssId = Aladin.DEFAULT_OPTIONS.survey;
|
||||
this.aladin.setBaseImageLayer(dssId);
|
||||
const idxServiceUrl = Math.round(Math.random());
|
||||
const dssUrl = Aladin.DEFAULT_OPTIONS.surveyUrl[idxServiceUrl]
|
||||
this.aladin.setBaseImageLayer(dssUrl);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1756,7 +1744,7 @@ export let View = (function () {
|
||||
projName = 'SIN'
|
||||
}
|
||||
|
||||
if (this.projection && this.projection.id === ProjectionEnum[projName].id) {
|
||||
if (this.projection.id === ProjectionEnum[projName].id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ import { CtxMenuActionButtonOpener } from "../Button/CtxMenuOpener.js";
|
||||
.then((catalogs) => {
|
||||
catalogs.forEach((cat) => {
|
||||
CatalogQueryBox.catalogs[cat.obs_title] = cat;
|
||||
CatalogQueryBox.catalogs[cat.ID] = cat;
|
||||
});
|
||||
|
||||
inputText.update({autocomplete: {options: Object.keys(CatalogQueryBox.catalogs)}})
|
||||
@@ -78,6 +77,7 @@ import { CtxMenuActionButtonOpener } from "../Button/CtxMenuOpener.js";
|
||||
);
|
||||
}
|
||||
else {
|
||||
console.log('cone search', params.baseURL)
|
||||
let url = params.baseURL;
|
||||
if (! url.endsWith('?')) {
|
||||
url += '?';
|
||||
@@ -248,11 +248,9 @@ import { CtxMenuActionButtonOpener } from "../Button/CtxMenuOpener.js";
|
||||
if (self.box) {
|
||||
self.box.remove();
|
||||
}
|
||||
// output the resulting cone search in the icrs frame
|
||||
self.box = new ConeSearchBox(aladin, {frame: 'icrs'});
|
||||
self.box = new ConeSearchBox(aladin);
|
||||
self.box.attach({
|
||||
callback: (cs) => {
|
||||
// the cone search services are asking for
|
||||
self.fnIdSelected('coneSearch', {
|
||||
baseURL: self.selectedItem.cs_service_url,
|
||||
id: self.selectedItem.ID,
|
||||
|
||||
@@ -33,7 +33,7 @@ import { Angle } from "../../libs/astro/angle.js";
|
||||
*****************************************************************************/
|
||||
|
||||
export class ConeSearchBox extends Box {
|
||||
constructor(aladin, options) {
|
||||
constructor(aladin) {
|
||||
let self;
|
||||
let selectorBtn = new ConeSearchActionButton({
|
||||
tooltip: {content: 'Select the area to query the catalogue with', position: {direction: 'left'}},
|
||||
@@ -43,8 +43,8 @@ import { Angle } from "../../libs/astro/angle.js";
|
||||
action(circle) {
|
||||
// convert to ra, dec and radius in deg
|
||||
try {
|
||||
let [ra, dec] = aladin.pix2world(circle.x, circle.y, options.frame);
|
||||
let radius = aladin.angularDist(circle.x, circle.y, circle.x + circle.r, circle.y, options.frame);
|
||||
let [ra, dec] = aladin.pix2world(circle.x, circle.y);
|
||||
let radius = aladin.angularDist(circle.x, circle.y, circle.x + circle.r, circle.y);
|
||||
|
||||
//var hlon = this.lon/15.0;
|
||||
//var strlon = Numbers.toSexagesimal(hlon, this.prec+1, false);
|
||||
@@ -160,6 +160,8 @@ import { Angle } from "../../libs/astro/angle.js";
|
||||
aladin.aladinDiv
|
||||
)
|
||||
|
||||
// hide by default
|
||||
//console.log("hide cone search")
|
||||
this._hide();
|
||||
|
||||
self = this;
|
||||
|
||||
@@ -41,8 +41,6 @@ import { Input } from "../Widgets/Input.js";
|
||||
.then((HiPSes) => {
|
||||
HiPSes.forEach((h) => {
|
||||
HiPSSelectorBox.HiPSList[h.obs_title] = h
|
||||
HiPSSelectorBox.HiPSList[h.ID] = h
|
||||
|
||||
});
|
||||
|
||||
inputText.update({autocomplete: {options: Object.keys(HiPSSelectorBox.HiPSList)}})
|
||||
|
||||
@@ -85,6 +85,10 @@ export class ServiceQueryBox extends Box {
|
||||
.catch((e) => {
|
||||
window.alert(e)
|
||||
})
|
||||
.finally(() => {
|
||||
// set cursor back to the normal mode
|
||||
//loadingBtn.remove();
|
||||
})
|
||||
},
|
||||
subInputs: []
|
||||
});
|
||||
@@ -152,6 +156,8 @@ export class ServiceQueryBox extends Box {
|
||||
self.form.set('ra', +lon)
|
||||
self.form.set('dec', +lat)
|
||||
self.form.set('rad', fov)
|
||||
|
||||
console.log(lon, lat, fov)
|
||||
} catch (e) {
|
||||
alert(e, 'Cone search out of projection')
|
||||
}
|
||||
|
||||
@@ -38,6 +38,14 @@ import { Icon } from "../Widgets/Icon";
|
||||
|
||||
export class StatusBarBox extends Box {
|
||||
constructor(aladin, options) {
|
||||
options.cssStyle = {
|
||||
color: 'white',
|
||||
backgroundColor: 'black',
|
||||
borderRadius: '3px',
|
||||
padding: 0,
|
||||
...options.cssStyle
|
||||
};
|
||||
|
||||
super(options, aladin.aladinDiv)
|
||||
|
||||
this.addClass("aladin-status-bar");
|
||||
@@ -122,12 +130,12 @@ export class StatusBarBox extends Box {
|
||||
position: {
|
||||
direction: "top",
|
||||
},
|
||||
hoverable: true,
|
||||
delayShowUpTime: '500ms',
|
||||
cssStyle: {
|
||||
fontSize: 'x-small',
|
||||
border: "1px solid white",
|
||||
fontSize: 'xx-small',
|
||||
maxWidth: "200px",
|
||||
"overflow-wrap": "break-word",
|
||||
"pointer-events": "auto",
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -43,8 +43,8 @@ export class ConeSearchActionButton extends ActionButton {
|
||||
// Constructor
|
||||
constructor(options, aladin) {
|
||||
super({
|
||||
size: 'medium',
|
||||
icon: {
|
||||
size: 'medium',
|
||||
monochrome: true,
|
||||
url: targetIconUrl
|
||||
},
|
||||
@@ -65,5 +65,7 @@ export class ConeSearchActionButton extends ActionButton {
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.addClass('medium-sized-icon')
|
||||
}
|
||||
}
|
||||
@@ -31,22 +31,19 @@
|
||||
import { ActionButton } from "../Widgets/ActionButton.js";
|
||||
import { ContextMenu } from "../Widgets/ContextMenu.js";
|
||||
|
||||
/*
|
||||
options = {
|
||||
action: (connector) => {
|
||||
|
||||
}
|
||||
tooltip
|
||||
}
|
||||
*/
|
||||
export class CtxMenuActionButtonOpener extends ActionButton {
|
||||
// Constructor
|
||||
constructor(options, aladin) {
|
||||
let self;
|
||||
|
||||
const enableTooltips = () => {
|
||||
aladin.aladinDiv.removeEventListener('click', enableTooltips);
|
||||
|
||||
aladin.aladinDiv.querySelectorAll('.aladin-tooltip')
|
||||
// for each tooltips reset its visibility and transition delay
|
||||
.forEach((t) => {
|
||||
t.style.visibility = ''
|
||||
t.style.transitionDelay = ''
|
||||
})
|
||||
};
|
||||
|
||||
super({
|
||||
...options,
|
||||
cssStyle: {
|
||||
@@ -55,8 +52,6 @@ export class CtxMenuActionButtonOpener extends ActionButton {
|
||||
...options.cssStyle
|
||||
},
|
||||
action(e) {
|
||||
enableTooltips()
|
||||
|
||||
let isHidden = self.ctxMenu.isHidden
|
||||
|
||||
ContextMenu.hideAll();
|
||||
@@ -78,15 +73,6 @@ export class CtxMenuActionButtonOpener extends ActionButton {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// the panel is now open and we know the button has a tooltip
|
||||
// => we close it!
|
||||
if (self.tooltip && !self.ctxMenu.isHidden) {
|
||||
self.tooltip.element().style.visibility = 'hidden'
|
||||
self.tooltip.element().style.transitionDelay = '0ms';
|
||||
|
||||
aladin.aladinDiv.addEventListener("click", enableTooltips)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -138,6 +124,7 @@ export class CtxMenuActionButtonOpener extends ActionButton {
|
||||
// it case it is not given then it will be computed by default
|
||||
direction: options.openDirection,
|
||||
},
|
||||
//cssStyle: options.ctxMenu && options.ctxMenu.cssStyle
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +52,7 @@ import { ALEvent } from "../../events/ALEvent";
|
||||
url: projectionIconUrl,
|
||||
},
|
||||
classList: ['aladin-projection-control'],
|
||||
//content: [options.verbosity === 'full' ? ProjectionEnum[projectionName].label : projectionName],
|
||||
content: projectionName,
|
||||
content: [options.verbosity === 'full' ? ProjectionEnum[projectionName].label : ''],
|
||||
tooltip: {content: 'Change the view projection', position: {direction: 'bottom left'}},
|
||||
cssStyle: {
|
||||
cursor: 'pointer',
|
||||
@@ -75,8 +74,8 @@ import { ALEvent } from "../../events/ALEvent";
|
||||
|
||||
ALEvent.PROJECTION_CHANGED.listenedBy(aladin.aladinDiv, function (e) {
|
||||
let projName = aladin.getProjectionName();
|
||||
//let content = self.options.verbosity === 'full' ? ProjectionEnum[projName].label : projName;
|
||||
let content = projName;
|
||||
let content = self.options.verbosity === 'full' ? ProjectionEnum[projName].label : '';
|
||||
|
||||
self.update({content})
|
||||
});
|
||||
}
|
||||
@@ -98,8 +97,7 @@ import { ALEvent } from "../../events/ALEvent";
|
||||
aladin.setProjection(key)
|
||||
|
||||
let ctxMenu = self._buildLayout(aladin);
|
||||
//self.update({ctxMenu, content: self.options.verbosity === 'full' ? proj.label : key});
|
||||
self.update({ctxMenu});
|
||||
self.update({ctxMenu, content: self.options.verbosity === 'full' ? proj.label : ''});
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -110,11 +108,11 @@ import { ALEvent } from "../../events/ALEvent";
|
||||
update(options) {
|
||||
super.update(options);
|
||||
|
||||
/*if (options.verbosity) {
|
||||
if (options.verbosity) {
|
||||
let ctxMenu = this._buildLayout();
|
||||
let projName = this.aladin.getProjectionName();
|
||||
let label = options.verbosity === 'full' ? ProjectionEnum[projName].label : projName;
|
||||
let label = options.verbosity === 'full' ? ProjectionEnum[projName].label : '';
|
||||
super.update({ctxMenu, content: label});
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ import { SettingsCtxMenu } from "../CtxMenu/Settings";
|
||||
},
|
||||
classList: ['aladin-settings-control'],
|
||||
tooltip: {
|
||||
content: 'Some general settings for the<br/>coordinate grid, the reticle or tools to enable',
|
||||
content: 'Some general settings e.g. background color, reticle, windows to show',
|
||||
position: {
|
||||
direction: 'right'
|
||||
direction: 'top right'
|
||||
}
|
||||
},
|
||||
ctxMenu: new SettingsCtxMenu(aladin, options),
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
import { CtxMenuActionButtonOpener } from "./CtxMenuOpener";
|
||||
import shareIconUrl from '../../../../assets/icons/share.svg';
|
||||
import cameraIconUrl from '../../../../assets/icons/camera.svg';
|
||||
import linkIconUrl from '../../../../assets/icons/link.svg';
|
||||
import jupyterIconUrl from '../../../../assets/icons/jupyter.svg';
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
@@ -47,16 +45,11 @@ import jupyterIconUrl from '../../../../assets/icons/jupyter.svg';
|
||||
let layout = [
|
||||
{
|
||||
label: {
|
||||
content: 'Get view URL',
|
||||
icon: {
|
||||
monochrome: true,
|
||||
url: linkIconUrl,
|
||||
size: 'small',
|
||||
},
|
||||
content: 'Save the view',
|
||||
tooltip: {
|
||||
content: 'View URL will be saved into your clipboard',
|
||||
position: {
|
||||
direction: 'right'
|
||||
direction: 'bottom'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -85,22 +78,32 @@ import jupyterIconUrl from '../../../../assets/icons/jupyter.svg';
|
||||
window.open(hips2fitsUrl, '_blank');
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Export to notebook',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
label: {
|
||||
content: 'Export to notebook',
|
||||
icon: {
|
||||
url: jupyterIconUrl,
|
||||
size: 'medium',
|
||||
},
|
||||
content: 'Save the WCS',
|
||||
tooltip: {
|
||||
content: '<i><font color="#ff0000">Not implemented</font></i><br/>Launch a notebook with <a href="https://github.com/cds-astro/ipyaladin" target="_blank"><font color="#fff">ipyaladin</font></a> inside.',
|
||||
hoverable: true,
|
||||
content: 'World Coordinate System of the view',
|
||||
position: {
|
||||
direction: 'right'
|
||||
}
|
||||
}
|
||||
},
|
||||
disabled: true,
|
||||
action(o) {
|
||||
let wcs = aladin.getViewWCS()
|
||||
navigator.clipboard.writeText(JSON.stringify(wcs));
|
||||
|
||||
if (aladin.statusBar) {
|
||||
aladin.statusBar.appendMessage({
|
||||
message: 'WCS saved into your clipboard!',
|
||||
duration: 2000,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: {
|
||||
@@ -110,7 +113,7 @@ import jupyterIconUrl from '../../../../assets/icons/jupyter.svg';
|
||||
url: cameraIconUrl,
|
||||
size: 'small',
|
||||
},
|
||||
content: 'Take a snapshot'
|
||||
content: 'Export as image file'
|
||||
},
|
||||
action(o) {
|
||||
aladin.exportAsPNG()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user