Compare commits
28 Commits
customize-
...
v3.7.3-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d244596ba | ||
|
|
2a23e83c13 | ||
|
|
7b8272795d | ||
|
|
4d8b4bfb21 | ||
|
|
ebf8845e83 | ||
|
|
f863ac902c | ||
|
|
75123e6bc8 | ||
|
|
d5d7d2a650 | ||
|
|
d22c25ea8a | ||
|
|
acef664b45 | ||
|
|
9e8db0379b | ||
|
|
032bb57517 | ||
|
|
f0fc39d2c8 | ||
|
|
2df32cb643 | ||
|
|
904d449006 | ||
|
|
2594aff1b6 | ||
|
|
547c5422d4 | ||
|
|
9bcc93877b | ||
|
|
3f6f247735 | ||
|
|
c6c7ad44c9 | ||
|
|
cdc1733c4f | ||
|
|
6e40dbbfc1 | ||
|
|
e03b16119b | ||
|
|
e3162426be | ||
|
|
5a285dabed | ||
|
|
2d04730623 | ||
|
|
390c9096d7 | ||
|
|
0e9998a7fc |
2
.github/workflows/npm-publish.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
npm install
|
||||
- name: "Build Aladin Lite"
|
||||
run: |
|
||||
npm run build
|
||||
npm run build:npm
|
||||
- name: "Publish Aladin Lite to npm"
|
||||
run: |
|
||||
npm publish
|
||||
|
||||
8
.gitignore
vendored
@@ -15,9 +15,11 @@ package-lock.json
|
||||
src/core/Cargo.lock
|
||||
src/core/target/
|
||||
|
||||
# this rust file is generated when compiling the code, so it is not
|
||||
# useful to put it on git
|
||||
src/core/src/shaders.rs
|
||||
# the tmp glsl files used when minifying the shaders into the wasm (build.rs)
|
||||
src/glsl/webgl2/**/*.min
|
||||
src/glsl/webgl2/**/*.tmp
|
||||
|
||||
package/
|
||||
|
||||
## python related
|
||||
# python environment
|
||||
|
||||
28
CHANGELOG.md
@@ -4,11 +4,33 @@
|
||||
|
||||
### What's Changed
|
||||
|
||||
* [perf] perform CPU computations with Vec3 and Matrix3 and not 4 dimensions matrices/vectors
|
||||
* [feat] lockNorthUp Aladin object new option locking the north pole up to the view center
|
||||
|
||||
## Released
|
||||
|
||||
### 3.7.0-beta
|
||||
|
||||
#### What's Changed
|
||||
|
||||
* [feat] flip longitude axis global method on Aladin by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/245>
|
||||
* [feat] add rotation event by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/283>
|
||||
* [docs] just fixing typo in image's doc by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/284>
|
||||
* [docs] change to an image with correct astrometry in example by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/290>
|
||||
* [docs] clarify use of precision in Coo by [@alexgoff][alexgoff] in <https://github.com/cds-astro/aladin-lite/pull/294>
|
||||
* [feat] allow setting HiPS CORS and credential options by [@pmatsson][pmatsson] in <https://github.com/cds-astro/aladin-lite/pull/281>
|
||||
* [feat] color picker and read pixel(s) API methods by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/280>
|
||||
* [fix] chandra hips display and akari by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/306>
|
||||
* [enhancement] update to the new version of fitsrs by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/310>
|
||||
* [fix] 26 channel color offset by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/320>
|
||||
* [fix] Circle intersectsBBox by [@emellega][emellega] in <https://github.com/cds-astro/aladin-lite/pull/309>
|
||||
* [feat] anti aliasing on lines plotted by the GPU by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/239>
|
||||
* [feat] source custom color and size from its data content by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/321>
|
||||
* [feat] catalog new select method by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/322>
|
||||
* [feat] HiPS 3D impl by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/314>
|
||||
* [feat] customize share URL function by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/327>
|
||||
* enhancement: use TAP entry point to query NED by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/257>
|
||||
* [perf] refac geometrical computations using Vec3/Mat3 instead of Vec4/Mat4 [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/276>
|
||||
* [fix] distortion at poles by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/247>
|
||||
* [feat] new aladin option `lockNorthUp` to keep north pole up [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/272>
|
||||
|
||||
### 3.6.3
|
||||
|
||||
#### What's Changed
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# [Aladin Lite](https://aladin.u-strasbg.fr/AladinLite)
|
||||
# [Aladin Lite](https://aladin.cds.unistra.fr/AladinLite)
|
||||
|
||||
**An astronomical HiPS visualizer in the browser** <img src="aladin-logo.png" alt="Aladin Lite logo" width="220">
|
||||
|
||||
@@ -8,14 +8,14 @@ See [A&A 578, A114 (2015)](https://arxiv.org/abs/1505.02291) and [IVOA HiPS Reco
|
||||
|
||||
Aladin Lite is built to be easily embeddable in any web page. It powers astronomical portals like [ESASky](https://sky.esa.int/), [ESO Science Archive portal](http://archive.eso.org/scienceportal/) and [ALMA Portal](https://almascience.eso.org/asax/).
|
||||
|
||||
More details on [Aladin Lite documentation page](http://aladin.u-strasbg.fr/AladinLite/doc/).
|
||||
More details on [Aladin Lite documentation page](http://aladin.cds.unistra.fr/AladinLite/doc/).
|
||||
A new [API technical documentation](https://cds-astro.github.io/aladin-lite/) is now available.
|
||||
|
||||
[](https://github.com/cds-astro/aladin-lite/actions/workflows/test.yml)
|
||||
[](https://cds-astro.github.io/aladin-lite)
|
||||
[](https://aladin.cds.unistra.fr/AladinLite/doc/release/)
|
||||
|
||||
Try Aladin Lite [here](https://aladin.u-strasbg.fr/AladinLite).
|
||||
Try Aladin Lite [here](https://aladin.cds.unistra.fr/AladinLite).
|
||||
|
||||
Aladin Lite is made possible thanks to pure Rust core libraries:
|
||||
* [cdshealpix](https://github.com/cds-astro/cds-healpix-rust) - for HEALPix projection and unprojection to/from sky coordinates
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"dateModified": "2023-01-31",
|
||||
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
|
||||
"name": "Aladin Lite",
|
||||
"version": "3.6.5",
|
||||
"softwareVersion": "3.6.5",
|
||||
"version": "3.7.2-beta",
|
||||
"softwareVersion": "3.7.2-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser.",
|
||||
"identifier": "10.5281/zenodo.7638833",
|
||||
"applicationCategory": "Astronomy, Visualization",
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
fov *= 0.997;
|
||||
rotation += 0.07;
|
||||
|
||||
aladin.setViewCenter2NorthPoleAngle(rotation)
|
||||
aladin.setRotation(rotation)
|
||||
aladin.setFoV(fov);
|
||||
|
||||
if (fov < 3 && fov > 0.5) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
aladin.setBaseImageLayer(dss);
|
||||
|
||||
dss.setCuts(2, 10000);
|
||||
dss.setCuts(2, 100, 'jpeg');
|
||||
|
||||
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
A.init.then(() => {
|
||||
// Start up Aladin Lite
|
||||
aladin = A.aladin('#aladin-lite-div', {target: 'M 1', fov: 0.2, showContextMenu: true, fullScreen: true});
|
||||
var overlay = A.graphicOverlay({color: '#ee2345', lineWidth: 3, lineDash: [2, 2]});
|
||||
var overlay = A.graphicOverlay({color: 'purple', lineWidth: 3, lineDash: [2, 2]});
|
||||
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'}),
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
showSimbadPointerControl: true,
|
||||
projection: 'AIT', // set a projection
|
||||
fov: 8.0, // initial field of view in degrees
|
||||
target: '00 42 21.37 +41 07 29.8', // initial target
|
||||
target: '10.6875598 +41.1402170', // initial target
|
||||
cooFrame: 'icrs', // set galactic frame
|
||||
reticleColor: '#ff89ff', // change reticle color
|
||||
showContextMenu: true,
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
);
|
||||
|
||||
hips = aladin.newImageSurvey("http://alasky.cds.unistra.fr/HIPS3D/GalfaHI", {
|
||||
hips = aladin.newImageSurvey("https://alasky.cds.unistra.fr/HIPS3D/LGLBSHI-test-compression/", {
|
||||
successCallback: (hips) => {
|
||||
//hips.setFrequency({value: 6.374279333565797E-7, unit: "m"}) // GALFA
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: "data/hips/CDS_P_DSS2_color", target: "05 40 59.12 -02 27 04.1", fov: 2, log: false});
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: "./data/hips/CDS_P_DSS2_color", target: "05 40 59.12 -02 27 04.1", fov: 2, log: false});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -7,31 +7,55 @@
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 30, survey: "CDS/P/GALEXGR6/AIS/FUV", target: "280 +0", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 30, target: "286.411023328 -37.3460065319", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
|
||||
|
||||
aladin.setOverlayImageLayer(A.image(
|
||||
"https://nova.astrometry.net/image/25038473?filename=M61.jpg",
|
||||
"data/img/m82.png",
|
||||
{
|
||||
name: "M61",
|
||||
name: "M82",
|
||||
wcs: {
|
||||
NAXIS: 2, // Minimal header
|
||||
CTYPE1: 'RA---TAN', // TAN (gnomic) projection
|
||||
CTYPE2: 'DEC--TAN', // TAN (gnomic) projection
|
||||
NAXIS: 2, // number of axes
|
||||
NAXIS1: 3000, // image width
|
||||
NAXIS2: 1918, // image height
|
||||
CTYPE3: "RGB", // Tell Aladin this is RGB
|
||||
WCSAXES: 2, // no comment
|
||||
CTYPE1: "RA---TAN", // TAN (gnomic) projection + SIP distortions
|
||||
CTYPE2: "DEC--TAN", // TAN (gnomic) projection + SIP distortions
|
||||
EQUINOX: 2000.0, // Equatorial coordinates definition (yr)
|
||||
LONPOLE: 180.0, // no comment
|
||||
LATPOLE: 0.0, // no comment
|
||||
CRVAL1: 185.445488837, // RA of reference point
|
||||
CRVAL2: 4.47896032431, // DEC of reference point
|
||||
CRPIX1: 588.995094299, // X reference pixel
|
||||
CRPIX2: 308.307905197, // Y reference pixel
|
||||
CUNIT1: 'deg', // X pixel scale units
|
||||
CUNIT2: 'deg', // Y pixel scale units
|
||||
CD1_1: -0.000223666022989, // Transformation matrix
|
||||
CD1_2: -0.000296578064584, // no comment
|
||||
CD2_1: -0.000296427555509, // no comment
|
||||
CD2_2: 0.000223774308964, // no comment
|
||||
NAXIS1: 1080, // Image width, in pixels.
|
||||
NAXIS2: 705 // Image height, in pixels.
|
||||
CRVAL1: 286.411023328, // RA of reference point
|
||||
CRVAL2: -37.3460065319, // DEC of reference point
|
||||
CRPIX1: 2264.1858724, // X reference pixel
|
||||
CRPIX2: 583.14634196, // Y reference pixel
|
||||
CUNIT1: "deg", // X pixel scale units
|
||||
CUNIT2: "deg", // Y pixel scale units
|
||||
CD1_1: -0.00284225200648, // Transformation matrix
|
||||
CD1_2: 0.00145908284254, // no comment
|
||||
CD2_1: -0.00145832184852, // no comment
|
||||
CD2_2: -0.0028440175499, // no comment
|
||||
A_ORDER: 2, // Polynomial order, axis 1
|
||||
A_0_0: 0, A_0_1: 0, A_0_2: 1.97760279295e-7,
|
||||
A_1_0: 0, A_1_1: 5.32298396638e-7,
|
||||
A_2_0: -2.16045473726e-6,
|
||||
B_ORDER: 2, // Polynomial order, axis 2
|
||||
B_0_0: 0, B_0_1: 0, B_0_2: 3.97377848239e-7,
|
||||
B_1_0: 0, B_1_1: -2.25823401545e-6,
|
||||
B_2_0: -1.47800507759e-7,
|
||||
AP_ORDER: 2, // Inv polynomial order, axis 1
|
||||
AP_0_0: 0.00617616810622,
|
||||
AP_0_1: -1.68315582233e-6,
|
||||
AP_0_2: -1.96504899588e-7,
|
||||
AP_1_0: -5.8320637913e-6,
|
||||
AP_1_1: -5.26081207663e-7,
|
||||
AP_2_0: 2.13760782681e-6,
|
||||
BP_ORDER: 2, // Inv polynomial order, axis 2
|
||||
BP_0_0: -0.000681183014773,
|
||||
BP_0_1: -2.15389849968e-7,
|
||||
BP_0_2: -3.94508397022e-7,
|
||||
BP_1_0: 4.51837961352e-6,
|
||||
BP_1_1: 2.24050293101e-6,
|
||||
BP_2_0: 1.49195269783e-7
|
||||
},
|
||||
successCallback: (ra, dec, fov, image) => {
|
||||
aladin.gotoRaDec(ra, dec);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
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: false, showSettingsControl: false, showLayersControl: true, showCooGrid: false, showFrame: false, showCooLocation: false});
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', lockNorthUp: true, fullScreen: true, fov: 360, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: false, showSettingsControl: false, showLayersControl: true, showCooGrid: true, showFrame: false, showCooLocation: false});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
});
|
||||
|
||||
aladin.addCatalog(A.catalogFromVizieR("B/assocdata/obscore", "0 +0", 20, {onClick: 'showTable', hoverColor: 'yellow', limit: 1000}))
|
||||
aladin.addCatalog(A.catalogFromSKAORucio("0 +0", 70, {onClick: 'showTable', hoverColor: 'yellow', limit: 1000}))
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -13,9 +13,15 @@
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {target: 'Gamma Cas', fov: 10, cooFrame: 'icrs'});
|
||||
|
||||
var overlay = A.graphicOverlay({lineWidth: 2});
|
||||
var overlay = A.graphicOverlay({color: 'green', lineWidth: 2});
|
||||
aladin.addOverlay(overlay);
|
||||
overlay.add(A.polyline([ [2.29452158, 59.14978110], [10.12683778, 56.53733116], [14.1772154, 60.7167403], [21.45396446, 60.23528403], [28.59885697, 63.67010079] ], {color: 'green'}));
|
||||
overlay.add(A.polyline([ [2.29452158, 59.14978110], [10.12683778, 56.53733116], [14.1772154, 60.7167403], [21.45396446, 60.23528403], [28.59885697, 63.67010079] ], {
|
||||
opacity: 0.7
|
||||
}));
|
||||
|
||||
aladin.on('rotationChanged', (rot) => {
|
||||
aladin.setRotation(rot)
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
let bValues = [];
|
||||
|
||||
let i = 0;
|
||||
for(var [r, g, b] of base.probe({type: 'line', x1: p.a.x, y1: p.a.y, x2: p.b.x, y2: p.b.y})) {
|
||||
for(var [r, g, b] of base.probePixels({type: 'line', x1: p.a.x, y1: p.a.y, x2: p.b.x, y2: p.b.y})) {
|
||||
xValues.push(i)
|
||||
rValues.push(r)
|
||||
gValues.push(g)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<script type="text/javascript">
|
||||
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});
|
||||
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, cooFrame: "ICRSd", showSimbadPointerControl: true, showShareControl: true, showShareControl: true, survey: 'https://jafar.astro.unistra.fr/data/jafar_hips/Surveys/CFIS/IC0750/asinh_0_1/', fov: 180, showContextMenu: true});
|
||||
// manage URL parameters
|
||||
const searchParams = new URL(document.location).searchParams;
|
||||
if (searchParams.has('baseImageLayer')) {
|
||||
|
||||
21
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"homepage": "https://aladin.u-strasbg.fr/",
|
||||
"homepage": "https://aladin.cds.unistra.fr/",
|
||||
"name": "aladin-lite",
|
||||
"type": "module",
|
||||
"version": "3.7.0-beta",
|
||||
"version": "3.7.3-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser",
|
||||
"author": "Thomas Boch and Matthieu Baumann",
|
||||
"license": "GPL-3",
|
||||
@@ -30,13 +30,17 @@
|
||||
"HiPS"
|
||||
],
|
||||
"scripts": {
|
||||
"wasm": "wasm-pack build ./src/core --target web --release --out-name core -- --features webgl2",
|
||||
"wasm:npm": "wasm-pack build ./src/core --target web --release --out-name core -- --features webgl2",
|
||||
"wasm:prod": "wasm-pack build ./src/core --target web --release --out-name core -- --features \"webgl2 minify_shaders\" && wasm-opt -Oz --strip-debug --strip-producers --dce -o src/core/pkg/core_bg.wasm src/core/pkg/core_bg.wasm",
|
||||
"wasm:dev": "wasm-pack build ./src/core --target web --release --out-name core -- --features webgl2",
|
||||
"wasm:dbg": "wasm-pack build --dev ./src/core --target web --out-name core -- --features=webgl2,dbg",
|
||||
"predeploy": "npm run build && rm -rf aladin-lite*.tgz && npm pack",
|
||||
"predeploy": "npm run build:prod && rm -rf aladin-lite*.tgz && npm pack",
|
||||
"deploy": "python3 deploy/deploy.py",
|
||||
"build": "npm run wasm && vite build",
|
||||
"build:npm": "npm run wasm:npm && vite build",
|
||||
"build:prod": "npm run wasm:prod && vite build",
|
||||
"build:dev": "npm run wasm:dev && vite build",
|
||||
"build:dbg": "npm run wasm:dbg && vite build",
|
||||
"dev": "npm run build && vite",
|
||||
"dev": "npm run build:dev && vite",
|
||||
"dev:dbg": "npm run build:dbg && vite",
|
||||
"serve": "npm run dev",
|
||||
"serve:dbg": "npm run dev:dbg",
|
||||
@@ -45,14 +49,15 @@
|
||||
"test:playwright": "npx playwright test",
|
||||
"test:update-snapshots": "npx playwright test --update-snapshots",
|
||||
"doc": "jsdoc -c jsdoc.json src/js src/js/shapes src/js/libs/astro && cp aladin-logo.png docs/ && cp jsdoc-custom-style.css docs/ && cp jsdoc-make-responsive.js docs/",
|
||||
"doc:dev": "npm run doc && open docs/index.html"
|
||||
"doc:dev": "npm run doc && open docs/index.html",
|
||||
"analyze": "vite build --mode analyze"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.47.0",
|
||||
"docdash": "^2.0.2",
|
||||
"jsdoc": "^4.0.2",
|
||||
"rollup-plugin-visualizer": "^6.0.3",
|
||||
"vite": "^4.3.8",
|
||||
"vite-plugin-glsl": "^1.1.2",
|
||||
"vite-plugin-top-level-await": "^1.4.1",
|
||||
"vite-plugin-wasm": "^3.2.2",
|
||||
"vite-plugin-wasm-pack": "^0.1.12"
|
||||
|
||||
@@ -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.7.0"
|
||||
version = "3.7.3-beta"
|
||||
authors = [ "baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr",]
|
||||
edition = "2018"
|
||||
|
||||
@@ -18,21 +18,20 @@ futures = "0.3.12"
|
||||
js-sys = "0.3.47"
|
||||
wasm-bindgen-futures = "0.4.20"
|
||||
cgmath = "*"
|
||||
# url-lite = "0.1.0"
|
||||
serde_json = "1.0.104"
|
||||
serde-wasm-bindgen = "0.5"
|
||||
enum_dispatch = "0.3.8"
|
||||
wasm-bindgen = "=0.2.92"
|
||||
#wasm-streams = "0.3.0"
|
||||
async-channel = "1.8.0"
|
||||
mapproj = "0.3.0"
|
||||
fitsrs = "0.3.4"
|
||||
colorgrad = "0.6.2"
|
||||
fitsrs = "0.4.1"
|
||||
|
||||
[features]
|
||||
webgl1 = [ "al-core/webgl1", "al-api/webgl1", "web-sys/WebGlRenderingContext", "web-sys/AngleInstancedArrays", "web-sys/ExtSRgb", "web-sys/OesTextureFloat",]
|
||||
webgl2 = [ "al-core/webgl2", "al-api/webgl2", "web-sys/WebGl2RenderingContext", "web-sys/WebGlVertexArrayObject", "web-sys/ExtColorBufferFloat",]
|
||||
dbg = [ "dep:console_error_panic_hook",]
|
||||
minify_shaders = []
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8"
|
||||
@@ -84,7 +83,7 @@ overflow-checks = false
|
||||
lto = true
|
||||
panic = "abort"
|
||||
incremental = false
|
||||
codegen-units = 16
|
||||
codegen-units = 1
|
||||
rpath = false
|
||||
|
||||
[package.metadata.wasm-pack.profile.release]
|
||||
|
||||
@@ -179,8 +179,9 @@ impl HiPSProperties {
|
||||
#[wasm_bindgen]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ImageExt {
|
||||
#[serde(alias = "fits", alias = "fits.fz")]
|
||||
Fits,
|
||||
#[serde(alias = "fits.fz")]
|
||||
FitsFz,
|
||||
Jpeg,
|
||||
Png,
|
||||
Webp,
|
||||
@@ -199,6 +200,7 @@ pub enum DataproductType {
|
||||
impl std::fmt::Display for ImageExt {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
ImageExt::FitsFz => write!(f, "fits.fz"),
|
||||
ImageExt::Fits => write!(f, "fits"),
|
||||
ImageExt::Png => write!(f, "png"),
|
||||
ImageExt::Jpeg => write!(f, "jpg"),
|
||||
|
||||
@@ -7,9 +7,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
js-sys = "0.3.47"
|
||||
cgmath = "*"
|
||||
#jpeg-decoder = "0.3.0"
|
||||
#png = "0.17.6"
|
||||
fitsrs = "0.3.4"
|
||||
fitsrs = "0.4.1"
|
||||
al-api = { path = "../al-api" }
|
||||
serde = { version = "^1.0.59", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use crate::texture::format::TextureFormat;
|
||||
use crate::texture::format::R8U;
|
||||
use cgmath::Vector3;
|
||||
use fitsrs::card::Value;
|
||||
use fitsrs::hdu::data::bintable::data::BinaryTableData;
|
||||
use fitsrs::hdu::data::bintable::tile_compressed::pixels::Pixels;
|
||||
use fitsrs::hdu::header::extension::bintable::TileCompressedImage;
|
||||
use fitsrs::hdu::header::Bitpix;
|
||||
use fitsrs::hdu::header::Header;
|
||||
use fitsrs::hdu::header::Xtension;
|
||||
use fitsrs::WCS;
|
||||
use fitsrs::{Fits, HDU};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Debug;
|
||||
use std::io::Cursor;
|
||||
use std::ops::Range;
|
||||
@@ -35,15 +36,7 @@ pub struct FitsImage<'a> {
|
||||
// bytes offset where the data bytes are located inside the fits
|
||||
pub data_byte_offset: Range<usize>,
|
||||
// raw bytes of the data image (in Big-Endian)
|
||||
pub raw_bytes: &'a [u8],
|
||||
}
|
||||
|
||||
fn parse_keyword_as_number<X: Xtension + Debug>(header: &Header<X>, keyword: &str) -> Option<f32> {
|
||||
match header.get(keyword) {
|
||||
Some(Value::Integer { value, .. }) => Some(*value as f32),
|
||||
Some(Value::Float { value, .. }) => Some(*value as f32),
|
||||
_ => None,
|
||||
}
|
||||
pub raw_bytes: Cow<'a, [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> FitsImage<'a> {
|
||||
@@ -57,22 +50,21 @@ impl<'a> FitsImage<'a> {
|
||||
HDU::XImage(hdu) | HDU::Primary(hdu) => {
|
||||
// Prefer getting the dimension directly from NAXIS1/NAXIS2 instead of from the WCS
|
||||
// because it may not exist in all HDU images
|
||||
let width = hdu.get_header().get_xtension().get_naxisn(1);
|
||||
let height = hdu.get_header().get_xtension().get_naxisn(2);
|
||||
|
||||
if let (Some(&width), Some(&height)) = (width, height) {
|
||||
let depth =
|
||||
*hdu.get_header().get_xtension().get_naxisn(3).unwrap_or(&1) as u32;
|
||||
let naxis = hdu.get_header().get_xtension().get_naxis();
|
||||
if naxis.len() >= 2 {
|
||||
let width = naxis[0];
|
||||
let height = naxis[1];
|
||||
let depth = if naxis.len() >= 3 { naxis[2] } else { 1 };
|
||||
|
||||
let header = hdu.get_header();
|
||||
|
||||
let bscale = parse_keyword_as_number(header, "BSCALE").unwrap_or(1.0);
|
||||
let bzero = parse_keyword_as_number(header, "BZERO").unwrap_or(0.0);
|
||||
let blank = parse_keyword_as_number(header, "BLANK");
|
||||
let bscale = header.get_parsed::<f32>("BSCALE").unwrap_or(1.0);
|
||||
let bzero = header.get_parsed::<f32>("BZERO").unwrap_or(0.0);
|
||||
let blank = header.get_parsed::<f32>("BLANK").ok();
|
||||
|
||||
let trim1 = parse_keyword_as_number(header, "TRIM1").unwrap_or(0.0) as u32;
|
||||
let trim2 = parse_keyword_as_number(header, "TRIM2").unwrap_or(0.0) as u32;
|
||||
let trim3 = parse_keyword_as_number(header, "TRIM3").unwrap_or(0.0) as u32;
|
||||
let trim1 = header.get_parsed::<u32>("TRIM1").unwrap_or(0);
|
||||
let trim2 = header.get_parsed::<u32>("TRIM2").unwrap_or(0);
|
||||
let trim3 = header.get_parsed::<u32>("TRIM3").unwrap_or(0);
|
||||
|
||||
let bitpix = hdu.get_header().get_xtension().get_bitpix();
|
||||
|
||||
@@ -80,7 +72,7 @@ impl<'a> FitsImage<'a> {
|
||||
let len = hdu.get_data_unit_byte_size() as usize;
|
||||
|
||||
let data_byte_offset = off..(off + len);
|
||||
let raw_bytes = &bytes[data_byte_offset.clone()];
|
||||
let raw_bytes = Cow::Borrowed(&bytes[data_byte_offset.clone()]);
|
||||
|
||||
let wcs = hdu.wcs().ok();
|
||||
|
||||
@@ -90,7 +82,7 @@ impl<'a> FitsImage<'a> {
|
||||
trim3,
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
depth,
|
||||
depth: depth as u32,
|
||||
bitpix,
|
||||
bscale,
|
||||
wcs,
|
||||
@@ -101,6 +93,81 @@ impl<'a> FitsImage<'a> {
|
||||
});
|
||||
}
|
||||
}
|
||||
HDU::XBinaryTable(hdu) => {
|
||||
let header = hdu.get_header();
|
||||
let bin_table = header.get_xtension();
|
||||
|
||||
if let Some(TileCompressedImage {
|
||||
z_bitpix: bitpix,
|
||||
z_naxisn: naxis,
|
||||
..
|
||||
}) = &bin_table.get_z_image()
|
||||
{
|
||||
if naxis.len() >= 2 {
|
||||
let width = naxis[0] as u32;
|
||||
let height = naxis[1] as u32;
|
||||
|
||||
let depth = if naxis.len() >= 3 { naxis[2] as u32 } else { 1 };
|
||||
|
||||
let bscale = header.get_parsed::<f32>("BSCALE").unwrap_or(1.0);
|
||||
let bzero = header.get_parsed::<f32>("BZERO").unwrap_or(0.0);
|
||||
let blank = header.get_parsed::<f32>("BLANK").ok();
|
||||
|
||||
let trim1 = header.get_parsed::<u32>("TRIM1").unwrap_or(0);
|
||||
let trim2 = header.get_parsed::<u32>("TRIM2").unwrap_or(0);
|
||||
let trim3 = header.get_parsed::<u32>("TRIM3").unwrap_or(0);
|
||||
|
||||
let wcs = hdu.wcs().ok();
|
||||
|
||||
let off = hdu.get_data_unit_byte_offset() as usize;
|
||||
let len = hdu.get_data_unit_byte_size() as usize;
|
||||
|
||||
let data_byte_offset = off..(off + len);
|
||||
|
||||
let mut bitpix = *bitpix;
|
||||
let raw_bytes = match fits.get_data(&hdu) {
|
||||
BinaryTableData::TileCompressed(Pixels::U8(pixels)) => {
|
||||
Some(pixels.collect::<Vec<_>>())
|
||||
}
|
||||
BinaryTableData::TileCompressed(Pixels::I16(pixels)) => {
|
||||
Some(pixels.flat_map(|p| p.to_be_bytes()).collect::<Vec<_>>())
|
||||
}
|
||||
BinaryTableData::TileCompressed(Pixels::I32(pixels)) => {
|
||||
Some(pixels.flat_map(|p| p.to_be_bytes()).collect::<Vec<_>>())
|
||||
}
|
||||
BinaryTableData::TileCompressed(Pixels::F32(pixels)) => {
|
||||
Some(pixels.flat_map(|p| p.to_be_bytes()).collect::<Vec<_>>())
|
||||
}
|
||||
BinaryTableData::TileCompressed(Pixels::F64(pixels)) => {
|
||||
bitpix = Bitpix::F32;
|
||||
let raw_bytes =
|
||||
pixels.flat_map(|p| p.to_be_bytes()).collect::<Vec<_>>();
|
||||
|
||||
Some(raw_bytes)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(raw_bytes) = raw_bytes {
|
||||
images.push(Self {
|
||||
trim1,
|
||||
trim2,
|
||||
trim3,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
bitpix,
|
||||
bscale,
|
||||
wcs,
|
||||
bzero,
|
||||
blank,
|
||||
data_byte_offset,
|
||||
raw_bytes: Cow::Owned(raw_bytes),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@@ -141,6 +208,7 @@ impl Image for FitsImage<'_> {
|
||||
R8U::view(&new_bytes)
|
||||
}
|
||||
Bitpix::F64 => {
|
||||
// convert to i64 first
|
||||
let new_bytes: Vec<_> = self
|
||||
.raw_bytes
|
||||
.chunks_exact(8)
|
||||
@@ -154,7 +222,7 @@ impl Image for FitsImage<'_> {
|
||||
|
||||
R8U::view(&new_bytes)
|
||||
}
|
||||
_ => R8U::view(self.raw_bytes),
|
||||
_ => R8U::view(&self.raw_bytes),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -93,8 +93,6 @@ pub trait VertexAttribPointerType: std::marker::Sized {
|
||||
}
|
||||
}
|
||||
use crate::webgl_ctx::WebGlRenderingCtx;
|
||||
use js_sys::WebAssembly;
|
||||
use wasm_bindgen::JsCast;
|
||||
impl VertexAttribPointerType for u8 {
|
||||
type ArrayBufferView = js_sys::Uint8Array;
|
||||
|
||||
@@ -308,7 +306,7 @@ impl VertexAttribPointerType for f32 {
|
||||
type ArrayBufferView = Float32Array;
|
||||
|
||||
fn array_buffer_view<'a, B: BufferDataStorage<'a, Self>>(data: B) -> Self::ArrayBufferView {
|
||||
let data = data.get_slice();
|
||||
/*let data = data.get_slice();
|
||||
//unsafe { Self::ArrayBufferView::view(&data) }
|
||||
let memory_buffer = wasm_bindgen::memory()
|
||||
.unchecked_ref::<WebAssembly::Memory>()
|
||||
@@ -316,7 +314,9 @@ impl VertexAttribPointerType for f32 {
|
||||
|
||||
let len = data.len();
|
||||
let ptr = data.as_ptr() as u32 / 4;
|
||||
Float32Array::new(&memory_buffer).subarray(ptr, ptr + len as u32)
|
||||
Float32Array::new(&memory_buffer).subarray(ptr, ptr + len as u32)*/
|
||||
let data = data.get_slice();
|
||||
unsafe { Self::ArrayBufferView::view(data) }
|
||||
}
|
||||
|
||||
fn buffer_sub_data_with_i32_and_array_buffer_view<'a, B: BufferDataStorage<'a, Self>>(
|
||||
@@ -462,6 +462,30 @@ impl ArrayBuffer {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*pub fn update_from_js_array<'a, T: VertexAttribPointerType>(
|
||||
&mut self,
|
||||
usage: u32,
|
||||
data: T::ArrayBufferView,
|
||||
) {
|
||||
self.bind();
|
||||
if self.len >= data.len() {
|
||||
T::buffer_sub_data_with_i32_and_array_buffer_view(
|
||||
&self.gl,
|
||||
data,
|
||||
WebGlRenderingCtx::ARRAY_BUFFER,
|
||||
);
|
||||
} else {
|
||||
self.len = data.len();
|
||||
|
||||
T::buffer_data_with_array_buffer_view(
|
||||
&self.gl,
|
||||
data,
|
||||
WebGlRenderingCtx::ARRAY_BUFFER,
|
||||
usage,
|
||||
);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
impl VertexBufferObject for ArrayBuffer {
|
||||
|
||||
@@ -132,6 +132,20 @@ pub mod vao {
|
||||
self
|
||||
}
|
||||
|
||||
/*pub fn update_from_js_array<T: VertexAttribPointerType>(
|
||||
&mut self,
|
||||
attr: &'static str,
|
||||
usage: u32,
|
||||
js_array: T::ArrayBufferView,
|
||||
) -> &mut Self {
|
||||
self.vao
|
||||
.array_buffer
|
||||
.get_mut(attr)
|
||||
.unwrap_abort()
|
||||
.update_from_js_array::<T>(usage, js_array);
|
||||
self
|
||||
}*/
|
||||
|
||||
pub fn update_element_array<T: VertexAttribPointerType, B: BufferDataStorage<'a, T>>(
|
||||
&mut self,
|
||||
usage: u32,
|
||||
|
||||
@@ -91,7 +91,7 @@ impl Texture2DArray {
|
||||
|
||||
// Attach the texture as the first color attachment
|
||||
self.gl.framebuffer_texture_layer(
|
||||
WebGlRenderingCtx::READ_FRAMEBUFFER,
|
||||
WebGlRenderingCtx::FRAMEBUFFER,
|
||||
WebGlRenderingCtx::COLOR_ATTACHMENT0,
|
||||
self.texture.as_ref(),
|
||||
0,
|
||||
|
||||
@@ -203,5 +203,3 @@ impl PixelType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const NUM_CHANNELS: usize = 6;
|
||||
|
||||
@@ -311,7 +311,7 @@ impl Texture2D {
|
||||
// Attach the texture as the first color attachment
|
||||
//self.attach_to_framebuffer();
|
||||
self.gl.framebuffer_texture_2d(
|
||||
WebGlRenderingCtx::READ_FRAMEBUFFER,
|
||||
WebGlRenderingCtx::FRAMEBUFFER,
|
||||
WebGlRenderingCtx::COLOR_ATTACHMENT0,
|
||||
WebGlRenderingCtx::TEXTURE_2D,
|
||||
self.texture.as_ref(),
|
||||
|
||||
@@ -21,32 +21,6 @@ pub trait Pixel:
|
||||
fn read_pixel(gl: &WebGlContext, x: i32, y: i32) -> Result<Self, JsValue>;
|
||||
}
|
||||
|
||||
impl Pixel for [f32; 1] {
|
||||
type Item = f32;
|
||||
type Container = ArrayF32;
|
||||
const BLACK: Self = [f32::NAN];
|
||||
|
||||
fn read_pixel(gl: &WebGlContext, x: i32, y: i32) -> Result<Self, JsValue> {
|
||||
let p = js_sys::Uint8Array::new_with_length(4);
|
||||
gl.read_pixels_with_opt_array_buffer_view(
|
||||
x,
|
||||
y,
|
||||
1,
|
||||
1,
|
||||
WebGlRenderingCtx::RGBA,
|
||||
WebGlRenderingCtx::UNSIGNED_BYTE,
|
||||
Some(&p),
|
||||
)?;
|
||||
|
||||
Ok([f32::from_le_bytes([
|
||||
p.at(0).unwrap(),
|
||||
p.at(1).unwrap(),
|
||||
p.at(2).unwrap(),
|
||||
p.at(3).unwrap(),
|
||||
])])
|
||||
}
|
||||
}
|
||||
|
||||
impl Pixel for [u8; 4] {
|
||||
type Item = u8;
|
||||
type Container = ArrayU8;
|
||||
@@ -74,13 +48,13 @@ impl Pixel for [u8; 3] {
|
||||
const BLACK: Self = [0, 0, 0];
|
||||
|
||||
fn read_pixel(gl: &WebGlContext, x: i32, y: i32) -> Result<Self, JsValue> {
|
||||
let pixels = js_sys::Uint8Array::new_with_length(3);
|
||||
let pixels = js_sys::Uint8Array::new_with_length(4);
|
||||
gl.read_pixels_with_opt_array_buffer_view(
|
||||
x,
|
||||
y,
|
||||
1,
|
||||
1,
|
||||
WebGlRenderingCtx::RGB,
|
||||
WebGlRenderingCtx::RGBA,
|
||||
WebGlRenderingCtx::UNSIGNED_BYTE,
|
||||
Some(&pixels),
|
||||
)?;
|
||||
@@ -147,7 +121,7 @@ impl Pixel for [i16; 1] {
|
||||
Some(&p),
|
||||
)?;
|
||||
|
||||
Ok([i16::from_le_bytes([p.at(0).unwrap(), p.at(1).unwrap()])])
|
||||
Ok([i16::from_le_bytes([p.at(1).unwrap(), p.at(0).unwrap()])])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,10 +143,36 @@ impl Pixel for [i32; 1] {
|
||||
)?;
|
||||
|
||||
Ok([i32::from_le_bytes([
|
||||
p.at(0).unwrap(),
|
||||
p.at(1).unwrap(),
|
||||
p.at(2).unwrap(),
|
||||
p.at(3).unwrap(),
|
||||
p.at(2).unwrap(),
|
||||
p.at(1).unwrap(),
|
||||
p.at(0).unwrap(),
|
||||
])])
|
||||
}
|
||||
}
|
||||
|
||||
impl Pixel for [f32; 1] {
|
||||
type Item = f32;
|
||||
type Container = ArrayF32;
|
||||
const BLACK: Self = [f32::NAN];
|
||||
|
||||
fn read_pixel(gl: &WebGlContext, x: i32, y: i32) -> Result<Self, JsValue> {
|
||||
let p = js_sys::Uint8Array::new_with_length(4);
|
||||
gl.read_pixels_with_opt_array_buffer_view(
|
||||
x,
|
||||
y,
|
||||
1,
|
||||
1,
|
||||
WebGlRenderingCtx::RGBA,
|
||||
WebGlRenderingCtx::UNSIGNED_BYTE,
|
||||
Some(&p),
|
||||
)?;
|
||||
|
||||
Ok([f32::from_le_bytes([
|
||||
p.at(3).unwrap(),
|
||||
p.at(2).unwrap(),
|
||||
p.at(1).unwrap(),
|
||||
p.at(0).unwrap(),
|
||||
])])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,12 +49,32 @@ impl WebGlContext {
|
||||
|
||||
#[cfg(feature = "webgl2")]
|
||||
{
|
||||
/*if let Ok(r) =
|
||||
get_extension::<web_sys::ExtColorBufferFloat>(&gl, "EXT_color_buffer_float")
|
||||
{
|
||||
let _ = r;
|
||||
}*/
|
||||
|
||||
let ctx = WebGlContext { inner: gl };
|
||||
Ok(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn _get_extension<T>(context: &WebGlRenderingCtx, name: &str) -> Result<T, JsValue>
|
||||
where
|
||||
T: wasm_bindgen::JsCast,
|
||||
{
|
||||
// `unchecked_into` is used here because WebGL extensions aren't actually JS classes
|
||||
// these objects are duck-type representations of the actual Rust classes
|
||||
// https://github.com/rustwasm/wasm-bindgen/pull/1449
|
||||
context
|
||||
.get_extension(name)
|
||||
.ok()
|
||||
.and_then(|maybe_ext| maybe_ext.map(|ext| ext.unchecked_into::<T>()))
|
||||
.ok_or_else(|| JsValue::from_str("Failed to load ext"))
|
||||
}
|
||||
|
||||
use std::ops::Deref;
|
||||
impl Deref for WebGlContext {
|
||||
type Target = WebGlRenderingCtx;
|
||||
|
||||
@@ -3,6 +3,8 @@ use walkdir::WalkDir;
|
||||
extern crate walkdir;
|
||||
use std::io::BufRead;
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
// All my shaders reside in the 'src/shaders' directory
|
||||
fn generate_shaders() -> std::result::Result<(), Box<dyn Error>> {
|
||||
println!("generate shaders");
|
||||
@@ -26,9 +28,48 @@ fn generate_shaders() -> std::result::Result<(), Box<dyn Error>> {
|
||||
.into_owned()
|
||||
.replace("/", "_")
|
||||
.replace("\\", "_");
|
||||
//let out_name = format!("{}/{}", OUT_PATH, out_file_name);
|
||||
|
||||
let src = read_shader(path)?;
|
||||
let mut src = read_shader(path)?;
|
||||
|
||||
if std::env::var("CARGO_FEATURE_MINIFY_SHADERS").is_ok() {
|
||||
println!("Feature `minify_shaders` enabled: running shader minifier");
|
||||
|
||||
// save to a minified path
|
||||
let mut tmp_path = PathBuf::from(path);
|
||||
let mut min_path = PathBuf::from(path);
|
||||
|
||||
let stem = path.file_stem().unwrap();
|
||||
// Build new filename: stem + ".min" + extension
|
||||
let tmp_file_name =
|
||||
format!("{}.{}.tmp", stem.to_string_lossy(), ext.to_string_lossy());
|
||||
tmp_path.set_file_name(tmp_file_name);
|
||||
|
||||
let min_file_name =
|
||||
format!("{}.{}.min", stem.to_string_lossy(), ext.to_string_lossy());
|
||||
min_path.set_file_name(min_file_name);
|
||||
|
||||
fs::write(tmp_path.clone(), &src)?;
|
||||
|
||||
Command::new("mono")
|
||||
.args([
|
||||
"/Users/matthieubaumann/Downloads/shader_minifier.exe",
|
||||
"--format",
|
||||
"text",
|
||||
"--aggressive-inlining",
|
||||
"--preserve-externals",
|
||||
"--move-declarations",
|
||||
"-o",
|
||||
min_path.as_os_str().to_str().expect("Invalid UTF-8!"),
|
||||
tmp_path.as_os_str().to_str().expect("Invalid UTF-8!"),
|
||||
])
|
||||
.status()
|
||||
.expect("Failed to run shader_minifier");
|
||||
|
||||
src = read_shader(min_path)?;
|
||||
} else {
|
||||
println!("Feature `minify_shaders` not enabled: skipping");
|
||||
}
|
||||
|
||||
shaders.insert(out_file_name, src);
|
||||
|
||||
println!("cargo:rerun-if-changed=src/shaders/{file_name}");
|
||||
|
||||
@@ -87,6 +87,7 @@ pub struct App {
|
||||
time_start_dragging: Time,
|
||||
time_mouse_high_vel: Time,
|
||||
dragging: bool,
|
||||
vel_history: Vec<f32>,
|
||||
|
||||
prev_cam_position: Vector3<f64>,
|
||||
//prev_center: Vector3<f64>,
|
||||
@@ -115,7 +116,7 @@ pub struct App {
|
||||
//callback_position_changed: js_sys::Function,
|
||||
}
|
||||
|
||||
use cgmath::{Vector2, Vector3};
|
||||
use cgmath::{Vector2, Vector3, Zero};
|
||||
|
||||
use crate::math::projection::*;
|
||||
pub const BLENDING_ANIM_DURATION: DeltaTime = DeltaTime::from_millis(200.0); // in ms
|
||||
@@ -208,6 +209,7 @@ impl App {
|
||||
|
||||
let browser_features_support = BrowserFeaturesSupport::new();
|
||||
|
||||
let vel_history = vec![];
|
||||
Ok(App {
|
||||
gl,
|
||||
//ui,
|
||||
@@ -244,6 +246,7 @@ impl App {
|
||||
time_start_dragging,
|
||||
time_mouse_high_vel,
|
||||
dragging,
|
||||
vel_history,
|
||||
|
||||
prev_cam_position,
|
||||
out_of_fov,
|
||||
@@ -264,6 +267,15 @@ impl App {
|
||||
})
|
||||
}
|
||||
|
||||
fn _update_hips_location(&mut self) {
|
||||
let camera = &self.camera;
|
||||
for hips in self.layers.get_mut_hipses() {
|
||||
if let HiPS::D3(hips) = hips {
|
||||
hips.set_cursor_location(camera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn look_for_new_tiles(&mut self) -> Result<(), JsValue> {
|
||||
// Move the views of the different active hipss
|
||||
self.tile_fetcher.clear();
|
||||
@@ -492,7 +504,7 @@ impl App {
|
||||
self.inertia.is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn update(&mut self, dt: DeltaTime) -> Result<bool, JsValue> {
|
||||
pub(crate) fn update(&mut self, dt: f64) -> Result<bool, JsValue> {
|
||||
// a timer stopping the frame if it takes too long
|
||||
// useful for garanting a framerate
|
||||
let rendering_timer = Time::now();
|
||||
@@ -505,7 +517,7 @@ impl App {
|
||||
// The threshold stopping criteria must be dependant
|
||||
// of the zoom level, in this case the initial angular distance
|
||||
// speed
|
||||
let thresh_speed = inertia.get_start_ampl() * 1e-3;
|
||||
let thresh_speed = inertia.get_start_ampl() * 1e-4;
|
||||
let cur_speed = inertia.get_cur_speed();
|
||||
|
||||
if cur_speed < thresh_speed {
|
||||
@@ -513,8 +525,6 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
self.draw()?;
|
||||
|
||||
// Check for async retrieval
|
||||
if let Ok(img) = self.img_recv.try_recv() {
|
||||
let params = img.get_params();
|
||||
@@ -545,7 +555,7 @@ impl App {
|
||||
.get_resolved_tiles(/*&available_tiles, */&mut self.hipss);*/
|
||||
|
||||
if self.request_for_new_tiles
|
||||
//&& Time::now() - self.last_time_request_for_new_tiles > DeltaTime::from(200.0)
|
||||
&& Time::now() - self.last_time_request_for_new_tiles > DeltaTime::from(500.0)
|
||||
{
|
||||
self.look_for_new_tiles()?;
|
||||
|
||||
@@ -557,9 +567,9 @@ impl App {
|
||||
let fetch_tiles =
|
||||
// * the user is not panning the view
|
||||
// * or the user is but did not move for at least 100ms
|
||||
(Time::now() - self.camera.get_time_of_last_move() >= DeltaTime(100.0) || !self.dragging) &&
|
||||
//(Time::now() - self.camera.get_time_of_last_move() >= DeltaTime(100.0) || !self.dragging) &&
|
||||
// * no inertia action is in progress
|
||||
self.inertia.is_none() &&
|
||||
//self.inertia.is_none() &&
|
||||
// * the user is not zooming
|
||||
!self.camera.has_zoomed();
|
||||
|
||||
@@ -572,7 +582,19 @@ impl App {
|
||||
|
||||
let mut tile_copied = false;
|
||||
|
||||
const MAX_FRAME_TIME: DeltaTime = DeltaTime::from_millis(1000.0 / 25.0);
|
||||
const MAX_FRAME_TIME: DeltaTime = DeltaTime::from_millis(1000.0 / 40.0);
|
||||
|
||||
// - there is at least one tile in its blending phase
|
||||
let blending_anim_occuring =
|
||||
(Time::now() - self.time_start_blending) < BLENDING_ANIM_DURATION;
|
||||
|
||||
self.rendering = blending_anim_occuring
|
||||
| has_camera_moved
|
||||
| self.camera.has_zoomed()
|
||||
| self.request_redraw
|
||||
| self.inertia.is_some();
|
||||
|
||||
self.draw()?;
|
||||
|
||||
for rsc in rscs_received {
|
||||
if Time::now() - rendering_timer >= MAX_FRAME_TIME {
|
||||
@@ -922,16 +944,6 @@ 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;
|
||||
|
||||
self.rendering = blending_anim_occuring
|
||||
| has_camera_moved
|
||||
| self.camera.has_zoomed()
|
||||
| self.request_redraw
|
||||
| self.inertia.is_some();
|
||||
|
||||
// Reset the flags about the user action
|
||||
self.camera.reset();
|
||||
|
||||
@@ -1028,64 +1040,63 @@ impl App {
|
||||
self.layers.reset_frame();*/
|
||||
|
||||
//let scene_redraw = self.rendering | force_render;
|
||||
let scene_redraw = true;
|
||||
|
||||
//let mut ui = self.ui.lock();
|
||||
//let ui_redraw = ui.redraw_needed();
|
||||
//if scene_redraw || ui_redraw {
|
||||
if scene_redraw {
|
||||
self.request_redraw = false;
|
||||
|
||||
let shaders = &mut self.shaders;
|
||||
self.request_redraw = false;
|
||||
|
||||
let gl = self.gl.clone();
|
||||
let shaders = &mut self.shaders;
|
||||
|
||||
let camera = &mut self.camera;
|
||||
let gl = self.gl.clone();
|
||||
|
||||
let grid = &mut self.grid;
|
||||
let moc = &mut self.moc;
|
||||
let projection = &self.projection;
|
||||
let camera = &mut self.camera;
|
||||
|
||||
let layers = &mut self.layers;
|
||||
//let catalogs = &self.manager;
|
||||
let colormaps = &self.colormaps;
|
||||
//let fbo_view = &self._fbo_view;
|
||||
//let final_rendering_pass = &self._final_rendering_pass;
|
||||
let grid = &mut self.grid;
|
||||
let moc = &mut self.moc;
|
||||
let projection = &self.projection;
|
||||
|
||||
//fbo_view.draw_onto(
|
||||
// move || {
|
||||
// Render the scene
|
||||
// Clear all the screen first (only the region set by the scissor)
|
||||
gl.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT);
|
||||
let layers = &mut self.layers;
|
||||
//let catalogs = &self.manager;
|
||||
let colormaps = &self.colormaps;
|
||||
//let fbo_view = &self._fbo_view;
|
||||
//let final_rendering_pass = &self._final_rendering_pass;
|
||||
|
||||
// set the blending options
|
||||
layers.draw(camera, shaders, colormaps, projection)?;
|
||||
//fbo_view.draw_onto(
|
||||
// move || {
|
||||
// Render the scene
|
||||
// Clear all the screen first (only the region set by the scissor)
|
||||
gl.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw the catalog
|
||||
//let fbo_view = &self.fbo_view;
|
||||
//catalogs.draw(&gl, shaders, camera, colormaps, fbo_view)?;
|
||||
//catalogs.draw(&gl, shaders, camera, colormaps, None, self.projection)?;
|
||||
/*gl.blend_func_separate(
|
||||
WebGl2RenderingContext::SRC_ALPHA,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
);*/
|
||||
moc.draw(camera, projection, shaders)?;
|
||||
// set the blending options
|
||||
layers.draw(camera, shaders, colormaps, projection)?;
|
||||
|
||||
/*gl.blend_func_separate(
|
||||
WebGl2RenderingContext::SRC_ALPHA,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
);*/
|
||||
grid.draw(camera, projection, shaders)?;
|
||||
// Ok(())
|
||||
// },
|
||||
// None,
|
||||
//)?;
|
||||
// Draw the catalog
|
||||
//let fbo_view = &self.fbo_view;
|
||||
//catalogs.draw(&gl, shaders, camera, colormaps, fbo_view)?;
|
||||
//catalogs.draw(&gl, shaders, camera, colormaps, None, self.projection)?;
|
||||
/*gl.blend_func_separate(
|
||||
WebGl2RenderingContext::SRC_ALPHA,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
);*/
|
||||
moc.draw(camera, projection, shaders)?;
|
||||
|
||||
//final_rendering_pass.draw_on_screen(fbo_view, &mut self.shaders)?;
|
||||
}
|
||||
/*gl.blend_func_separate(
|
||||
WebGl2RenderingContext::SRC_ALPHA,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
WebGl2RenderingContext::ONE,
|
||||
);*/
|
||||
grid.draw(camera, projection, shaders)?;
|
||||
// Ok(())
|
||||
// },
|
||||
// None,
|
||||
//)?;
|
||||
|
||||
//final_rendering_pass.draw_on_screen(fbo_view, &mut self.shaders)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1220,7 +1231,7 @@ impl App {
|
||||
&gl,
|
||||
wcs,
|
||||
bitpix,
|
||||
raw_bytes,
|
||||
raw_bytes.as_ref(),
|
||||
bscale,
|
||||
bzero,
|
||||
blank,
|
||||
@@ -1529,6 +1540,8 @@ impl App {
|
||||
|
||||
// And stop the current inertia as well if there is one
|
||||
self.inertia = None;
|
||||
|
||||
self._update_hips_location();
|
||||
}
|
||||
|
||||
pub(crate) fn move_mouse(&mut self, s1x: f32, s1y: f32, s2x: f32, s2y: f32) {
|
||||
@@ -1538,7 +1551,16 @@ impl App {
|
||||
let dx = crate::math::vector::dist2(&from_mouse_pos, &to_mouse_pos).sqrt();
|
||||
self.dist_dragging += dx;
|
||||
|
||||
//let now = Time::now();
|
||||
//let dragging_duration = (now - self.time_start_dragging).as_secs();
|
||||
//let dragging_vel = self.dist_dragging / dragging_duration;
|
||||
|
||||
// 1. Use smoothed velocity instead of instantaneous velocity
|
||||
let dv = dx / (Time::now() - self.camera.get_time_of_last_move()).as_secs();
|
||||
self.vel_history.push(dv);
|
||||
if self.vel_history.len() > 5 {
|
||||
self.vel_history.remove(0);
|
||||
}
|
||||
|
||||
if dv > 10000.0 {
|
||||
self.time_mouse_high_vel = Time::now();
|
||||
@@ -1587,15 +1609,18 @@ impl App {
|
||||
}
|
||||
|
||||
let now = Time::now();
|
||||
let dragging_duration = (now - self.time_start_dragging).as_secs();
|
||||
let dragging_vel = self.dist_dragging / dragging_duration;
|
||||
let avg_vel = self.vel_history.iter().copied().sum::<f32>() / self.vel_history.len() as f32;
|
||||
|
||||
// Detect if there has been a recent acceleration
|
||||
// It is also possible that the dragging time is too short and if it is the case, trigger the inertia
|
||||
let recent_acceleration = (Time::now() - self.time_mouse_high_vel).as_secs() < 0.1
|
||||
|| (Time::now() - self.time_start_dragging).as_secs() < 0.1;
|
||||
// 2. Clamp minimum + maximum velocities
|
||||
let min_vel = 1000.0; // tweak
|
||||
|
||||
if dragging_vel < 2000.0 && !recent_acceleration {
|
||||
// 3. Better condition for “recent acceleration”
|
||||
let t_since_drag = (now - self.time_start_dragging).as_secs();
|
||||
let t_since_accel = (now - self.time_mouse_high_vel).as_secs();
|
||||
|
||||
let inertia_trigger =
|
||||
avg_vel > min_vel || ((t_since_drag < 0.15) || (t_since_accel < 0.15));
|
||||
if !inertia_trigger {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1605,10 +1630,8 @@ impl App {
|
||||
let center = self.camera.get_center();
|
||||
let axis = self.prev_cam_position.cross(*center).normalize();
|
||||
|
||||
//let delta_time = ((now - time_of_last_move).0 as f64).max(1.0);
|
||||
let delta_angle = math::vector::angle3(&self.prev_cam_position, center).to_radians();
|
||||
let ampl = delta_angle * (dragging_vel as f64) * 5e-3;
|
||||
//let ampl = (dragging_vel * 0.01) as f64;
|
||||
let ampl = (delta_angle * avg_vel as f64) * 5e-3;
|
||||
|
||||
self.inertia = Some(Inertia::new(ampl.to_radians(), axis, self.north_up))
|
||||
}
|
||||
@@ -1718,7 +1741,6 @@ impl App {
|
||||
}
|
||||
} else {
|
||||
/* 1. Rotate by computing the angle between the last and current position */
|
||||
|
||||
let d = math::vector::angle3(&prev_pos, &cur_pos);
|
||||
let axis = prev_pos.cross(cur_pos).normalize();
|
||||
|
||||
@@ -1728,9 +1750,39 @@ impl App {
|
||||
|
||||
self.prev_cam_position = prev_cam_position;
|
||||
self.request_for_new_tiles = true;
|
||||
|
||||
self._update_hips_location();
|
||||
}
|
||||
} else {
|
||||
self.out_of_fov = true;
|
||||
// approx move
|
||||
let origin2next = Vector2::new(s2x - s1x, s2y - s1y);
|
||||
|
||||
if origin2next != Vector2::zero() {
|
||||
let prev_pos = self.camera.get_center();
|
||||
|
||||
let prev_cam_position = self.get_center().vector();
|
||||
|
||||
let center_screen = self
|
||||
.projection
|
||||
.model_to_screen_space(&prev_cam_position, &self.camera)
|
||||
.unwrap();
|
||||
|
||||
let next_s = origin2next + center_screen;
|
||||
|
||||
if let Some(cur_pos) = self.projection.screen_to_model_space(&next_s, &self.camera)
|
||||
{
|
||||
let d = math::vector::angle3(prev_pos, &cur_pos);
|
||||
let axis = prev_pos.cross(cur_pos).normalize();
|
||||
|
||||
self.camera
|
||||
.apply_axis_rotation(&(-axis), d, &self.projection);
|
||||
|
||||
self.prev_cam_position = prev_cam_position;
|
||||
self.request_for_new_tiles = true;
|
||||
|
||||
self._update_hips_location();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1758,6 +1810,8 @@ impl App {
|
||||
pub(crate) fn set_zoom_factor(&mut self, zoom_factor: f64) {
|
||||
self.camera.set_zoom_factor(zoom_factor, &self.projection);
|
||||
|
||||
self._update_hips_location();
|
||||
|
||||
self.request_for_new_tiles = true;
|
||||
self.request_redraw = true;
|
||||
}
|
||||
|
||||
@@ -570,42 +570,48 @@ impl CameraViewPort {
|
||||
}
|
||||
|
||||
fn compute_texture_depth(&mut self) {
|
||||
/*// Compute a depth from a number of pixels on screen
|
||||
let width = self.width;
|
||||
let aperture = self.aperture.0 as f32;
|
||||
// Compute a depth from a number of pixels on screen
|
||||
/*let width = self.width;
|
||||
let aperture = self.aperture as f32;
|
||||
|
||||
let angle_per_pixel = aperture / width;
|
||||
let angle_per_pixel = aperture / width;
|
||||
|
||||
let two_power_two_times_depth_pixel =
|
||||
std::f32::consts::PI / (3.0 * angle_per_pixel * angle_per_pixel);
|
||||
let depth_pixel = (two_power_two_times_depth_pixel.log2() / 2.0).floor() as u32;
|
||||
let two_power_two_times_depth_pixel =
|
||||
std::f32::consts::PI / (3.0 * angle_per_pixel * angle_per_pixel);
|
||||
let depth_pixel = (two_power_two_times_depth_pixel.log2() / 2.0).ceil() as u32;
|
||||
|
||||
//let survey_max_depth = conf.get_max_depth();
|
||||
// The depth of the texture
|
||||
// A texture of 512x512 pixels will have a depth of 9
|
||||
const DEPTH_OFFSET_TEXTURE: u32 = 9;
|
||||
// The depth of the texture corresponds to the depth of a pixel
|
||||
// minus the offset depth of the texture
|
||||
self.texture_depth = if DEPTH_OFFSET_TEXTURE > depth_pixel {
|
||||
0_u8
|
||||
} else {
|
||||
(depth_pixel - DEPTH_OFFSET_TEXTURE) as u8
|
||||
};*/
|
||||
//let survey_max_depth = conf.get_max_depth();
|
||||
// The depth of the texture
|
||||
// A texture of 512x512 pixels will have a depth of 9
|
||||
const DEPTH_OFFSET_TEXTURE: u32 = 9;
|
||||
// The depth of the texture corresponds to the depth of a pixel
|
||||
// minus the offset depth of the texture
|
||||
self.texture_depth = if DEPTH_OFFSET_TEXTURE > depth_pixel {
|
||||
0_u8
|
||||
} else {
|
||||
(depth_pixel - DEPTH_OFFSET_TEXTURE) as u8
|
||||
};
|
||||
*/
|
||||
let w_screen_device_px = self.width as f64 / (self.dpi as f64);
|
||||
//let depth_pixel = 29_usize;
|
||||
|
||||
let w_screen_px = self.width as f64;
|
||||
let smallest_cell_size_px = self.dpi as f64;
|
||||
let mut depth_pixel = 29_usize;
|
||||
let pixel_angle_rad = self.get_aperture() / w_screen_device_px;
|
||||
|
||||
let hpx_cell_size_rad = (smallest_cell_size_px / w_screen_px) * self.get_aperture();
|
||||
|
||||
while depth_pixel > 0 {
|
||||
if crate::healpix::utils::MEAN_HPX_CELL_RES[depth_pixel] > hpx_cell_size_rad {
|
||||
break;
|
||||
// Find the smallest depth such that MEAN_HPX_CELL_RES[depth] > pixel_angle_rad
|
||||
let depth_pixel = match crate::healpix::utils::MEAN_HPX_CELL_RES.binary_search_by(|&res| {
|
||||
if res < pixel_angle_rad {
|
||||
std::cmp::Ordering::Greater
|
||||
} else if res > pixel_angle_rad {
|
||||
std::cmp::Ordering::Less
|
||||
} else {
|
||||
std::cmp::Ordering::Equal
|
||||
}
|
||||
}) {
|
||||
Ok(idx) => idx, // exact match
|
||||
Err(idx) => idx,
|
||||
};
|
||||
|
||||
depth_pixel -= 1;
|
||||
}
|
||||
depth_pixel += 1;
|
||||
//al_core::log(&format!("{:?}", depth_pixel));
|
||||
const DEPTH_OFFSET_TEXTURE: usize = 9;
|
||||
self.texture_depth = if DEPTH_OFFSET_TEXTURE > depth_pixel {
|
||||
0_u8
|
||||
|
||||
@@ -96,11 +96,7 @@ impl Downloader {
|
||||
}
|
||||
|
||||
pub fn delay(&mut self, r: RequestType) {
|
||||
match r {
|
||||
RequestType::Tile(tile) => {
|
||||
self.cache.insert(tile.id.clone(), RequestType::Tile(tile));
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
let id = r.id().to_owned();
|
||||
self.cache.insert(id, r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ impl From<query::Allsky> for AllskyRequest {
|
||||
|
||||
let FitsImage {
|
||||
raw_bytes, bitpix, ..
|
||||
} = FitsImage::from_raw_bytes(raw_bytes.as_slice())?[0];
|
||||
} = &FitsImage::from_raw_bytes(raw_bytes.as_slice())?[0];
|
||||
match bitpix {
|
||||
Bitpix::U8 => {
|
||||
Ok(handle_allsky_fits(raw_bytes, tile_size, allsky_tile_size)?
|
||||
|
||||
@@ -133,8 +133,9 @@ async fn query_html_image(
|
||||
// Set the CORS and credentials options for the image
|
||||
let cors_value = match credentials {
|
||||
RequestCredentials::Include => Some("use-credentials"),
|
||||
RequestCredentials::SameOrigin => Some("anonymous"),
|
||||
_ => Some(""),
|
||||
RequestCredentials::Omit => Some("anonymous"),
|
||||
RequestCredentials::SameOrigin => Some(""),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let promise = js_sys::Promise::new(
|
||||
|
||||
@@ -3,7 +3,6 @@ use cgmath::Vector3;
|
||||
use crate::camera::CameraViewPort;
|
||||
use crate::math::angle::ToAngle;
|
||||
use crate::math::projection::ProjectionType;
|
||||
use crate::time::{DeltaTime, Time};
|
||||
/// State for inertia
|
||||
pub struct Inertia {
|
||||
// Initial angular distance
|
||||
@@ -12,21 +11,20 @@ pub struct Inertia {
|
||||
// Vector of rotation
|
||||
axis: Vector3<f64>,
|
||||
// The time when the inertia begins
|
||||
time_start: Time,
|
||||
north_up: bool,
|
||||
}
|
||||
|
||||
impl Inertia {
|
||||
pub fn new(ampl: f64, axis: Vector3<f64>, north_up: bool) -> Self {
|
||||
Inertia {
|
||||
time_start: Time::now(),
|
||||
ampl,
|
||||
speed: ampl,
|
||||
speed: (ampl * 0.5).min(0.1),
|
||||
axis,
|
||||
north_up,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn apply(&mut self, camera: &mut CameraViewPort, proj: &ProjectionType, _dt: DeltaTime) {
|
||||
let t = ((Time::now() - self.time_start).as_millis() / 1000.0) as f64;
|
||||
// Undamped angular frequency of the oscillator
|
||||
@@ -46,6 +44,27 @@ impl Inertia {
|
||||
let fov = start_fov * (1_f32 - alpha) + goal_fov * alpha;*/
|
||||
camera.apply_axis_rotation(&self.axis, self.speed.to_angle(), proj);
|
||||
|
||||
if self.north_up {
|
||||
camera.set_position_angle(0.0.to_angle(), proj);
|
||||
}
|
||||
}*/
|
||||
|
||||
pub fn apply(&mut self, camera: &mut CameraViewPort, proj: &ProjectionType, dt: f64) {
|
||||
// Initial angular velocity
|
||||
//let v0 = self.ampl * 0.5;
|
||||
|
||||
// Friction coefficient (tweak this)
|
||||
const DAMPING_FACTOR: f64 = 5e-3;
|
||||
|
||||
self.speed *= (-DAMPING_FACTOR * dt).exp();
|
||||
let delta_angle = self.speed * dt;
|
||||
|
||||
// Exponential decay of angular velocity
|
||||
// self.speed = (v0 * (-damping * t).exp()).min(3.0);
|
||||
|
||||
//camera.apply_axis_rotation(&self.axis, self.speed.to_angle(), proj);
|
||||
camera.apply_axis_rotation(&self.axis, delta_angle.to_angle(), proj);
|
||||
|
||||
if self.north_up {
|
||||
camera.set_position_angle(0.0.to_angle(), proj);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//extern crate num;
|
||||
//extern crate num_traits;
|
||||
//use crate::time::Time;
|
||||
|
||||
#[cfg(feature = "dbg")]
|
||||
use std::panic;
|
||||
|
||||
@@ -115,7 +116,6 @@ mod time;
|
||||
|
||||
use crate::{
|
||||
camera::CameraViewPort, healpix::moc::SpaceMoc, math::lonlat::LonLatT, shader::ShaderManager,
|
||||
time::DeltaTime,
|
||||
};
|
||||
|
||||
use al_api::color::{Color, ColorRGBA};
|
||||
@@ -136,10 +136,6 @@ use math::angle::ArcDeg;
|
||||
pub struct WebClient {
|
||||
// The app
|
||||
app: App,
|
||||
|
||||
// The time between the previous and the current
|
||||
// frame
|
||||
dt: DeltaTime,
|
||||
}
|
||||
|
||||
use al_api::hips::ImageMetadata;
|
||||
@@ -166,9 +162,7 @@ impl WebClient {
|
||||
|
||||
let app = App::new(&gl, aladin_div, shaders, resources)?;
|
||||
|
||||
let dt = DeltaTime::zero();
|
||||
|
||||
let webclient = WebClient { app, dt };
|
||||
let webclient = WebClient { app };
|
||||
|
||||
Ok(webclient)
|
||||
}
|
||||
@@ -193,15 +187,15 @@ impl WebClient {
|
||||
///
|
||||
/// # Return
|
||||
/// Whether the view is moving or not
|
||||
pub fn update(&mut self, dt: f32) -> Result<bool, JsValue> {
|
||||
pub fn update(&mut self, dt: f64) -> Result<bool, JsValue> {
|
||||
// dt refers to the time taking (in ms) rendering the previous frame
|
||||
self.dt = DeltaTime::from_millis(dt);
|
||||
//self.dt = DeltaTime::from_millis(dt as f32);
|
||||
|
||||
// Update the application and get back the
|
||||
// world coordinates of the center of projection in (ra, dec)
|
||||
self.app.update(
|
||||
// Time of the previous frame rendering
|
||||
self.dt,
|
||||
dt,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -111,27 +111,50 @@ where
|
||||
// Define a rotation from an axis and a angle
|
||||
pub fn from_axis_angle(axis: &Vector3<S>, angle: Angle<S>) -> Rotation<S> {
|
||||
let angle: Rad<S> = angle.into();
|
||||
let mat = Matrix3::from_axis_angle(axis.normalize(), angle);
|
||||
(&mat).into()
|
||||
let half = angle.0 * S::from(0.5).unwrap();
|
||||
|
||||
let (s, c) = half.sin_cos();
|
||||
let axis = axis.normalize();
|
||||
|
||||
let q = Quaternion::new(c, axis.x * s, axis.y * s, axis.z * s);
|
||||
Rotation(q)
|
||||
}
|
||||
|
||||
// Define a rotation from a normalized vector
|
||||
pub fn from_sky_position(pos: &Vector3<S>) -> Rotation<S> {
|
||||
let (lon, lat) = math::lonlat::xyz_to_radec(pos);
|
||||
|
||||
let qy = Self::from_axis_angle(&Vector3::unit_y(), lon);
|
||||
let qx = Self::from_axis_angle(&Vector3::unit_x(), -lat);
|
||||
|
||||
qy * qx
|
||||
}
|
||||
|
||||
/*pub fn from_sky_position(pos: &Vector3<S>) -> Rotation<S> {
|
||||
let (lon, lat) = math::lonlat::xyz_to_radec(pos);
|
||||
|
||||
let rot_y = Matrix3::from_angle_y(lon);
|
||||
let rot_x = Matrix3::from_angle_x(-lat);
|
||||
|
||||
let mat = rot_y * rot_x;
|
||||
(&(mat)).into()
|
||||
}
|
||||
}*/
|
||||
|
||||
// Apply a rotation to a position
|
||||
pub fn rotate(&self, pos_world_space: &Vector3<S>) -> Vector3<S> {
|
||||
let w2m: &Matrix3<S> = &self.into();
|
||||
pub fn rotate(&self, v: &Vector3<S>) -> Vector3<S> {
|
||||
/*let w2m: &Matrix3<S> = &self.into();
|
||||
w2m * v*/
|
||||
let qvec = self.0.v; // vector part of the quaternion
|
||||
|
||||
w2m * pos_world_space
|
||||
// uv = qvec × v
|
||||
let uv = qvec.cross(*v);
|
||||
// uuv = qvec × uv
|
||||
let uuv = qvec.cross(uv);
|
||||
|
||||
// v' = v + 2 * (uv * q.w + uuv)
|
||||
*v + ((uv * self.0.s) + uuv) * (S::from(2.0).unwrap())
|
||||
}
|
||||
|
||||
pub fn inv_rotate(&self, pos_model_space: &Vector3<S>) -> Vector3<S> {
|
||||
let w2m: &Matrix3<S> = &self.into();
|
||||
let m2w = w2m.transpose();
|
||||
|
||||
@@ -77,7 +77,7 @@ impl HiPSConfig {
|
||||
}
|
||||
|
||||
let format = match img_ext {
|
||||
ImageExt::Fits => {
|
||||
ImageExt::Fits | ImageExt::FitsFz => {
|
||||
// Check the bitpix to determine the internal format of the tiles
|
||||
if let Some(bitpix) = bitpix {
|
||||
let fmt = (match bitpix {
|
||||
@@ -176,7 +176,7 @@ impl HiPSConfig {
|
||||
|
||||
pub fn set_image_ext(&mut self, ext: ImageExt) -> Result<(), JsValue> {
|
||||
let format = match ext {
|
||||
ImageExt::Fits => {
|
||||
ImageExt::Fits | ImageExt::FitsFz => {
|
||||
// Check the bitpix to determine the internal format of the tiles
|
||||
if let Some(bitpix) = self.bitpix {
|
||||
let fmt = (match bitpix {
|
||||
|
||||
@@ -77,34 +77,37 @@ fn create_hpx_texture_storage(
|
||||
WebGlRenderingCtx::TEXTURE_WRAP_T,
|
||||
WebGlRenderingCtx::CLAMP_TO_EDGE,
|
||||
),
|
||||
// Prevents r-coordinate wrapping (repeating)
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_WRAP_R,
|
||||
WebGlRenderingCtx::CLAMP_TO_EDGE,
|
||||
),
|
||||
];
|
||||
match channel {
|
||||
PixelType::RGBA8U => Texture2DArray::create_empty::<RGBA8U>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
num_tiles, tex_params,
|
||||
),
|
||||
PixelType::RGB8U => Texture2DArray::create_empty::<RGB8U>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
num_tiles, tex_params,
|
||||
),
|
||||
PixelType::RGBA8U => {
|
||||
Texture2DArray::create_empty::<RGBA8U>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
num_tiles, tex_params,
|
||||
)
|
||||
}
|
||||
PixelType::RGB8U => {
|
||||
Texture2DArray::create_empty::<RGB8U>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
num_tiles, tex_params,
|
||||
)
|
||||
}
|
||||
PixelType::R32F => Texture2DArray::create_empty::<R32F>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
num_tiles, tex_params,
|
||||
),
|
||||
|
||||
PixelType::R8U => Texture2DArray::create_empty::<R8U>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
num_tiles, tex_params,
|
||||
),
|
||||
|
||||
PixelType::R16I => Texture2DArray::create_empty::<R16I>(
|
||||
gl, tile_size, tile_size,
|
||||
// 256 is a consensus for targetting the maximum GPU architectures. We create a 128 slices to optimize performance
|
||||
@@ -285,7 +288,7 @@ impl HiPS2DBuffer {
|
||||
.tile_pixels
|
||||
.read_pixel(pos_tex.x, pos_tex.y, pos_tex.z)?,
|
||||
_ => {
|
||||
let uvy = 1.0 - (pos_tex.y as f32 / tile_size);
|
||||
let uvy = 1.0 - (dx as f32);
|
||||
pos_tex.y = (uvy * tile_size) as i32;
|
||||
|
||||
let f64_v = self
|
||||
|
||||
@@ -219,6 +219,9 @@ pub struct HiPS2D {
|
||||
//#[cfg(feature = "webgl1")]
|
||||
// layout (location = 0) in vec3 position;
|
||||
position: Vec<f32>,
|
||||
//js_position: Float32Array,
|
||||
//cap: usize,
|
||||
//ptr: usize,
|
||||
//#[cfg(feature = "webgl1")]
|
||||
// layout (location = 1) in vec3 uv_start;
|
||||
uv_start: Vec<f32>,
|
||||
@@ -235,7 +238,6 @@ pub struct HiPS2D {
|
||||
|
||||
vao: VertexArrayObject,
|
||||
gl: WebGlContext,
|
||||
|
||||
moc: Option<SpaceMoc>,
|
||||
|
||||
// A buffer storing the cells in the view
|
||||
@@ -304,6 +306,7 @@ impl HiPS2D {
|
||||
let gl = gl.clone();
|
||||
let moc = None;
|
||||
let hpx_cells_in_view = vec![];
|
||||
|
||||
// request the allsky texture
|
||||
Ok(Self {
|
||||
// The image survey texture buffer
|
||||
@@ -494,6 +497,7 @@ impl HiPS2D {
|
||||
}
|
||||
|
||||
fn recompute_vertices(&mut self, camera: &mut CameraViewPort, projection: &ProjectionType) {
|
||||
//al_core::log(&format!("num position: {:?}", self.position.len()));
|
||||
self.position.clear();
|
||||
self.uv_start.clear();
|
||||
self.uv_end.clear();
|
||||
|
||||
@@ -4,11 +4,16 @@ pub mod texture;
|
||||
use crate::browser_support::BrowserFeaturesSupport;
|
||||
use crate::healpix::moc::FreqSpaceMoc;
|
||||
use crate::math::angle::ToAngle;
|
||||
use crate::math::lonlat;
|
||||
use crate::math::lonlat::LonLatT;
|
||||
use crate::math::spectra::SpectralUnit;
|
||||
use crate::math::spectra::FREQ_MAX;
|
||||
use crate::math::spectra::FREQ_MIN;
|
||||
|
||||
use crate::coosys;
|
||||
|
||||
use crate::CooSystem;
|
||||
|
||||
use crate::tile_fetcher::TileFetcherQueue;
|
||||
use al_api::hips::DataproductType;
|
||||
use al_api::hips::ImageExt;
|
||||
@@ -400,9 +405,6 @@ impl HiPS3D {
|
||||
camera: &CameraViewPort,
|
||||
browser_features_support: &BrowserFeaturesSupport,
|
||||
) {
|
||||
// update the cursor center before downloading new tiles
|
||||
self.set_cursor_location(camera.get_center().into(), camera);
|
||||
|
||||
// do not add tiles if the view is already at depth 0
|
||||
let cfg = self.get_config();
|
||||
let depth_tile = camera
|
||||
@@ -589,7 +591,7 @@ impl HiPS3D {
|
||||
let mut start = window_pixel_hash.start.max(domain_pixel_hash.start);
|
||||
let mut end = window_pixel_hash.end.min(domain_pixel_hash.end);
|
||||
|
||||
if start < end {
|
||||
if start <= end {
|
||||
start = start - pixel_hash_0 - indices.start;
|
||||
end = end - pixel_hash_0 - indices.start;
|
||||
|
||||
@@ -657,7 +659,15 @@ impl HiPS3D {
|
||||
crate::event::send_custom_event("spectra", JsValue::from(spectra_js_obj));
|
||||
}
|
||||
|
||||
pub fn set_cursor_location(&mut self, lonlat: LonLatT<f64>, camera: &CameraViewPort) {
|
||||
pub fn set_cursor_location(&mut self, camera: &CameraViewPort) {
|
||||
let (lon, lat) = lonlat::xyz_to_radec(&coosys::apply_coo_system(
|
||||
camera.get_coo_system(),
|
||||
CooSystem::ICRS,
|
||||
camera.get_center(),
|
||||
));
|
||||
|
||||
let lonlat = LonLatT(lon, lat);
|
||||
|
||||
let cfg = self.get_config();
|
||||
let s_order = camera
|
||||
.get_tile_depth()
|
||||
@@ -915,6 +925,9 @@ impl HiPS3D {
|
||||
idx + off_indices,
|
||||
idx + 3 + off_indices,
|
||||
]);
|
||||
|
||||
idx += 4;
|
||||
|
||||
// GL LINES
|
||||
/*self.idx_vertices.extend([
|
||||
idx + off_indices,
|
||||
@@ -929,8 +942,6 @@ impl HiPS3D {
|
||||
idx + 3 + off_indices,
|
||||
idx + off_indices,
|
||||
]);*/
|
||||
|
||||
idx += 4;
|
||||
}
|
||||
|
||||
off_indices += pos.len() as u16;
|
||||
@@ -946,23 +957,21 @@ impl HiPS3D {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut vao = self.vao.bind_for_update();
|
||||
vao.update_array(
|
||||
"position",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData(&self.position),
|
||||
)
|
||||
.update_array(
|
||||
"uv",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData(&self.uv),
|
||||
)
|
||||
.update_element_array(
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData(&self.idx_vertices),
|
||||
);
|
||||
}
|
||||
let mut vao = self.vao.bind_for_update();
|
||||
vao.update_array(
|
||||
"position",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData(&self.position),
|
||||
)
|
||||
.update_array(
|
||||
"uv",
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData(&self.uv),
|
||||
)
|
||||
.update_element_array(
|
||||
WebGl2RenderingContext::DYNAMIC_DRAW,
|
||||
VecData(&self.idx_vertices),
|
||||
);
|
||||
}
|
||||
|
||||
fn reset_available_tiles(&mut self) -> bool {
|
||||
|
||||
@@ -11,6 +11,7 @@ use al_core::texture::Texture3D;
|
||||
use al_core::webgl_ctx::WebGlRenderingCtx;
|
||||
use cgmath::Vector3;
|
||||
use fitsrs::hdu::header::Bitpix;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::Range;
|
||||
use wasm_bindgen::JsValue;
|
||||
@@ -283,37 +284,45 @@ impl HpxFreqTex {
|
||||
) -> Result<(), JsValue> {
|
||||
let raw_bytes = raw_bytes.to_vec().into_boxed_slice();
|
||||
|
||||
let (trim1, trim2, trim3, width, height, depth, bitpix, data_byte_offset, bscale, bzero) = {
|
||||
let fits = FitsImage::from_raw_bytes(&raw_bytes[..])?;
|
||||
fits[0].insert_into_3d_texture(&self.texture, &Vector3::<i32>::new(0, 0, 0))?;
|
||||
self.data = {
|
||||
let image = FitsImage::from_raw_bytes(&raw_bytes[..])?.pop().unwrap();
|
||||
image.insert_into_3d_texture(&self.texture, &Vector3::<i32>::new(0, 0, 0))?;
|
||||
|
||||
(
|
||||
fits[0].trim1,
|
||||
fits[0].trim2,
|
||||
fits[0].trim3,
|
||||
fits[0].width,
|
||||
fits[0].height,
|
||||
fits[0].depth,
|
||||
fits[0].bitpix,
|
||||
fits[0].data_byte_offset.clone(),
|
||||
fits[0].bscale,
|
||||
fits[0].bzero,
|
||||
)
|
||||
let bitpix = image.bitpix;
|
||||
let trim = (image.trim1, image.trim2, image.trim3);
|
||||
let naxis = (image.width, image.height, image.depth);
|
||||
let bscale = image.bscale;
|
||||
let bzero = image.bzero;
|
||||
|
||||
if let Cow::Owned(uncompressed_bytes) = image.raw_bytes {
|
||||
Some(HpxFreqData::Fits {
|
||||
data_byte_offset: 0..uncompressed_bytes.len(),
|
||||
raw_bytes: uncompressed_bytes.into_boxed_slice(),
|
||||
bitpix,
|
||||
trim,
|
||||
naxis,
|
||||
bscale,
|
||||
bzero,
|
||||
size,
|
||||
})
|
||||
} else {
|
||||
let data_byte_offset = image.data_byte_offset.clone();
|
||||
|
||||
std::mem::drop(image);
|
||||
|
||||
Some(HpxFreqData::Fits {
|
||||
raw_bytes,
|
||||
data_byte_offset,
|
||||
bitpix,
|
||||
trim,
|
||||
naxis,
|
||||
bscale,
|
||||
bzero,
|
||||
size,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let trim = (trim1, trim2, trim3);
|
||||
let naxis = (width, height, depth);
|
||||
|
||||
self.data = Some(HpxFreqData::Fits {
|
||||
raw_bytes,
|
||||
data_byte_offset: data_byte_offset.clone(),
|
||||
bitpix,
|
||||
trim,
|
||||
naxis,
|
||||
bscale,
|
||||
bzero,
|
||||
size,
|
||||
});
|
||||
self.num_stored_slices = self.num_slices;
|
||||
self.start_time = Some(Time::now());
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ fn get_coord_uv_it(
|
||||
)
|
||||
.chain(std::iter::once((
|
||||
xmax,
|
||||
if xmax % max_tex_size == 0 {
|
||||
if xmax.is_multiple_of(max_tex_size) {
|
||||
1.0
|
||||
} else {
|
||||
get_uv_in_tex_chunk(xmax)
|
||||
@@ -129,7 +129,7 @@ fn get_coord_uv_it(
|
||||
})
|
||||
.chain(std::iter::once((
|
||||
xmax,
|
||||
if xmax % max_tex_size == 0 {
|
||||
if xmax.is_multiple_of(max_tex_size) {
|
||||
1.0
|
||||
} else {
|
||||
get_uv_in_tex_chunk(xmax)
|
||||
@@ -199,7 +199,9 @@ pub fn vertices(
|
||||
};
|
||||
|
||||
x_it.clone().map(move |(x, uvx)| {
|
||||
let ndc = if let Some(xyz) = wcs.unproj_xyz(&ImgXY::new(x as f64, y as f64)) {
|
||||
let ndc = if let Some(xyz) =
|
||||
wcs.unproj_xyz(&ImgXY::new(x as f64 + 0.5, y as f64 + 0.5))
|
||||
{
|
||||
let xyz = crate::coosys::apply_coo_system(
|
||||
CooSystem::ICRS,
|
||||
camera.get_coo_system(),
|
||||
|
||||
@@ -162,7 +162,10 @@ impl Image {
|
||||
|
||||
// Compute the fov
|
||||
let center = wcs
|
||||
.unproj_lonlat(&ImgXY::new(width as f64 / 2.0, height as f64 / 2.0))
|
||||
.unproj_lonlat(&ImgXY::new(
|
||||
(width as f64 / 2.0) + 0.5,
|
||||
(height as f64 / 2.0) + 0.5,
|
||||
))
|
||||
.ok_or(JsValue::from_str("(w / 2, h / 2) px cannot be unprojected"))?;
|
||||
let center_xyz = center.to_xyz();
|
||||
let inside = crate::coosys::apply_coo_system(
|
||||
@@ -172,13 +175,13 @@ impl Image {
|
||||
);
|
||||
|
||||
let vertices = [
|
||||
wcs.unproj_lonlat(&ImgXY::new(0.0, 0.0))
|
||||
wcs.unproj_lonlat(&ImgXY::new(0.5, 0.5))
|
||||
.ok_or(JsValue::from_str("(0, 0) does not lie in the sky"))?,
|
||||
wcs.unproj_lonlat(&ImgXY::new(width as f64 - 1.0, 0.0))
|
||||
wcs.unproj_lonlat(&ImgXY::new(width as f64 - 0.5, 0.5))
|
||||
.ok_or(JsValue::from_str("(w - 1, 0) does not lie in the sky"))?,
|
||||
wcs.unproj_lonlat(&ImgXY::new(width as f64 - 1.0, height as f64 - 1.0))
|
||||
wcs.unproj_lonlat(&ImgXY::new(width as f64 - 0.5, height as f64 - 0.5))
|
||||
.ok_or(JsValue::from_str("(w - 1, h - 1) does not lie in the sky"))?,
|
||||
wcs.unproj_lonlat(&ImgXY::new(0.0, height as f64 - 1.0))
|
||||
wcs.unproj_lonlat(&ImgXY::new(0.5, height as f64 - 0.5))
|
||||
.ok_or(JsValue::from_str("(0, h - 1) does not lie in the sky"))?,
|
||||
]
|
||||
.iter()
|
||||
@@ -669,7 +672,10 @@ impl Image {
|
||||
// let's redefine the region
|
||||
let center = self
|
||||
.wcs
|
||||
.unproj_lonlat(&ImgXY::new(width as f64 / 2.0, height as f64 / 2.0))
|
||||
.unproj_lonlat(&ImgXY::new(
|
||||
(width as f64 / 2.0) + 0.5,
|
||||
(height as f64 / 2.0) + 0.5,
|
||||
))
|
||||
.ok_or(JsValue::from_str("(w / 2, h / 2) px cannot be unprojected"))?;
|
||||
let center_xyz = center.to_xyz();
|
||||
let inside = crate::coosys::apply_coo_system(
|
||||
@@ -680,16 +686,16 @@ impl Image {
|
||||
|
||||
let vertices = [
|
||||
self.wcs
|
||||
.unproj_lonlat(&ImgXY::new(0.0, 0.0))
|
||||
.unproj_lonlat(&ImgXY::new(0.5, 0.5))
|
||||
.ok_or(JsValue::from_str("(0, 0) does not lie in the sky"))?,
|
||||
self.wcs
|
||||
.unproj_lonlat(&ImgXY::new(width as f64 - 1.0, 0.0))
|
||||
.unproj_lonlat(&ImgXY::new(width as f64 - 0.5, 0.5))
|
||||
.ok_or(JsValue::from_str("(w - 1, 0) does not lie in the sky"))?,
|
||||
self.wcs
|
||||
.unproj_lonlat(&ImgXY::new(width as f64 - 1.0, height as f64 - 1.0))
|
||||
.unproj_lonlat(&ImgXY::new(width as f64 - 0.5, height as f64 - 0.5))
|
||||
.ok_or(JsValue::from_str("(w - 1, h - 1) does not lie in the sky"))?,
|
||||
self.wcs
|
||||
.unproj_lonlat(&ImgXY::new(0.0, height as f64 - 1.0))
|
||||
.unproj_lonlat(&ImgXY::new(0.5, height as f64 - 0.5))
|
||||
.ok_or(JsValue::from_str("(0, h - 1) does not lie in the sky"))?,
|
||||
]
|
||||
.iter()
|
||||
|
||||
@@ -88,7 +88,7 @@ where
|
||||
|
||||
pixels_written += num_pixels_to_read;
|
||||
|
||||
if F::PIXEL_TYPE.num_channels() == 1 && y % step_cut == 0 {
|
||||
if F::PIXEL_TYPE.num_channels() == 1 && y.is_multiple_of(step_cut) {
|
||||
// on a good line
|
||||
let bytes_line = &buf[id_tx][off_bytes_dst..(off_bytes_dst + num_bytes_to_read)];
|
||||
for x_in_patch in (0..w_patch).step_by(step_cut) {
|
||||
@@ -153,7 +153,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
if (((dy + 1) % (max_tex_size as usize) == 0) && id_tx == buf.len() - 1)
|
||||
if ((dy + 1).is_multiple_of(max_tex_size as usize) && id_tx == buf.len() - 1)
|
||||
|| pixels_written >= num_pixels
|
||||
{
|
||||
// we can create new textures of size max_tex_size
|
||||
|
||||
@@ -454,7 +454,11 @@ impl Layers {
|
||||
// HiPS cube
|
||||
DataproductType::Cube => HiPS::D3(HiPS3D::new(cfg, gl, &layer)?),
|
||||
// HiPS 3D
|
||||
DataproductType::SpectralCube => HiPS::D3(HiPS3D::new(cfg, gl, &layer)?),
|
||||
DataproductType::SpectralCube => {
|
||||
let mut hips = HiPS3D::new(cfg, gl, &layer)?;
|
||||
hips.set_cursor_location(camera);
|
||||
HiPS::D3(hips)
|
||||
}
|
||||
// Typical HiPS image
|
||||
_ => HiPS::D2(HiPS2D::new(cfg, gl)?),
|
||||
};
|
||||
|
||||
@@ -28,4 +28,16 @@ where
|
||||
pub fn is_ccw(&self) -> bool {
|
||||
crate::math::utils::ccw_tri(self.v1, self.v2, self.v3)
|
||||
}
|
||||
|
||||
pub fn is_elongated(&self) -> bool {
|
||||
let mag2_12 = (self.v1[0] - self.v2[0]) * (self.v1[0] - self.v2[0])
|
||||
+ (self.v1[1] - self.v2[1]) * (self.v1[1] - self.v2[1]);
|
||||
let mag2_13 = (self.v1[0] - self.v3[0]) * (self.v1[0] - self.v3[0])
|
||||
+ (self.v1[1] - self.v3[1]) * (self.v1[1] - self.v3[1]);
|
||||
let mag2_23 = (self.v2[0] - self.v3[0]) * (self.v2[0] - self.v3[0])
|
||||
+ (self.v2[1] - self.v3[1]) * (self.v2[1] - self.v3[1]);
|
||||
|
||||
let l = S::from(0.2).unwrap();
|
||||
mag2_12 >= l || mag2_23 >= l || mag2_13 >= l
|
||||
}
|
||||
}
|
||||
|
||||
246
src/core/src/shaders.rs
Normal file
@@ -0,0 +1,246 @@
|
||||
use std::collections::HashMap;
|
||||
#[allow(dead_code)]
|
||||
pub fn get_all() -> HashMap<&'static str, &'static str> {
|
||||
let mut out = HashMap::new();
|
||||
out.insert(
|
||||
r"hips_raytracer_f32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;precision mediump int;in vec3 frag_pos;in vec2 out_clip_pos;out vec4 out_frag_color;struct Tile{int uniq;int texture_idx;float start_time;float empty;};uniform Tile textures_tiles[12];uniform float opacity;uniform sampler2DArray tex;struct TileColor{Tile tile;vec4 color;bool found;};uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float t(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float f(float f){f=t(f);return f*f;}float v(float v){return H==0?t(v):H==1?sqrt(t(v)):H==2?log(1e3*t(v)+1.)/log(1e3):H==3?asinh(10.*t(v))/3.:f(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}highp float s(highp vec4 v){highp float f=2.*mod(v[0],128.)+step(128.,v[1])-127.;return abs(f+127.)<.001?0.:(1.-step(128.,v[0])*2.)*exp2(f)*((mod(v[1],128.)*65536.+v[2]*256.+v[3]+float(8388608))*exp2(-23.));}vec4 s(float s){float i=v(s*scale+offset);i=mix(i,1.-i,reversed);vec4 H=mix(texture(colormaps,vec2(i,(colormap_id+.5)/num_colormaps)),vec4(0),float(isinf(s)));return f(t(v(vec4(H.xyz+k_brightness,H.w))));}int f(vec2 v){int f=int(v.y<0.);return int(v.x<0.)+f|f<<1;}float s(vec2 v){float f=atan(abs(v.y),abs(v.x))*1.27323954474;return v.x<0.!=v.y<0.?1.-f:f-1.;}float f(vec3 v){float f=dot(v.xy,v.xy);return f<.1?f*(.5+f*(.125+f*(.0625+f*(.0390625+f*.02734375)))):1.f-v.z;}float s(vec3 v){float f=dot(v.xy,v.xy);return f<.1f?f*(.5+f*(.125+f*(.0625+f*(.0390625+f*.02734375)))):v.z+1.;}int f(int v,int f){v|=f<<2;f=(v^v>>1)&572662306;return v^f^f<<1;}struct HashDxDy{int idx;float dx;float dy;};uniform sampler2D ang2pixd;HashDxDy t(vec3 v){float H=float(1<<0)*.5,t=s(v.xy),e,i;int a=f(v.xy),r=0,u,m;vec2 o=vec2(0);if(v.z>.66666666666){float s=sqrt(3.*f(v));o=vec2(t*s,2.-s);r=a;}else if(v.z<-.66666666666){float f=sqrt(3.*s(v));o=vec2(t*f,f);r=a+8;}else{float f=v.z*1.5;int i=int(t>f),e=int(t>=-f),H=1-e;o=vec2(t-float(i+e-1),f+float(i+H));r=(i+H<<2)+(a+(i&e)&3);}e=H*(o.x+o.y);i=H*(o.y-o.x);u=int(e);m=int(i);return HashDxDy((r<<(0<<1))+f(u,m),e-float(u),i-float(m));}vec3 f(){HashDxDy v=t(normalize(frag_pos).zxy);return vec3(vec2(v.dy,v.dx),float(textures_tiles[v.idx].texture_idx));}void main(){vec3 v=f();v.y=1.-v.y;vec4 i=s(s(texture(tex,v).xyzw*255.));out_frag_color=i;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_rgba.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;uniform sampler2DArray tex;in vec3 frag_uv_start,frag_uv_end;in float frag_blending_factor;out vec4 out_frag_color;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float v(float v){v=f(v);return v*v;}float t(float t){return H==0?f(t):H==1?sqrt(f(t)):H==2?log(1e3*f(t)+1.)/log(1e3):H==3?asinh(10.*f(t))/3.:v(t);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 f){return vec4(pow(f.x,k_gamma),pow(f.y,k_gamma),pow(f.z,k_gamma),f.w);}vec4 t(vec4 f){return vec4(mix(vec3(dot(f.xyz,vec3(.2126,.7152,.0722))),f.xyz,1.+k_saturation),f.w);}vec4 v(vec4 f){return vec4(.5+(1.+k_contrast)*(f.xyz-.5),f.w);}vec4 f(vec3 a){vec4 r=texture(tex,a).xyzw;r.x=t(r.x);r.y=t(r.y);r.z=t(r.z);r.xyz=mix(r.xyz,1.-r.xyz,reversed);return f(t(v(vec4(r.xyz+k_brightness,r.w))));}void main(){out_frag_color=mix(f(frag_uv_start),f(frag_uv_end),frag_blending_factor);out_frag_color.w=opacity*out_frag_color.w;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"moc_base.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;out vec4 color;uniform vec4 u_color;void main(){color=u_color;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"fits_f32.frag",
|
||||
r#"#version 300 es
|
||||
precision highp float;precision highp sampler2D;precision highp int;out vec4 out_frag_color;in vec2 frag_uv;uniform sampler2D tex;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float v(float v){v=f(v);return v*v;}float t(float t){return H==0?f(t):H==1?sqrt(f(t)):H==2?log(1e3*f(t)+1.)/log(1e3):H==3?asinh(10.*f(t))/3.:v(t);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}highp float h(highp vec4 v){highp float t=2.*mod(v[0],128.)+step(128.,v[1])-127.;return abs(t+127.)<.001?0.:(1.-step(128.,v[0])*2.)*exp2(t)*((mod(v[1],128.)*65536.+v[2]*256.+v[3]+float(8388608))*exp2(-23.));}vec4 h(float h){float s=t(h*scale+offset);s=mix(s,1.-s,reversed);vec4 H=mix(texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps)),vec4(0),float(isinf(h)));return f(t(v(vec4(H.xyz+k_brightness,H.w))));}void main(){out_frag_color=h(h(texture(tex,frag_uv).xyzw*255.));out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"fits_u8.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2D;precision mediump int;out vec4 out_frag_color;in vec2 frag_uv;uniform sampler2D tex;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}vec4 m(float H){float m=v(H*scale+offset);m=mix(m,1.-m,reversed);vec4 k=mix(texture(colormaps,vec2(m,(colormap_id+.5)/num_colormaps)),vec4(0),float(H==blank||isnan(H)));return f(t(v(vec4(k.xyz+k_brightness,k.w))));}void main(){out_frag_color=m(float(uint(texture(tex,frag_uv).x*255.+.5)));out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"image_base.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;layout(location=0)in vec2 ndc_pos;layout(location=1)in vec2 uv;out vec2 frag_uv;void main(){gl_Position=vec4(ndc_pos,0,1);frag_uv=uv;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips3d_f32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler3D;uniform sampler3D tex;in vec3 frag_uv;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float v(float v){v=f(v);return v*v;}float s(float t){return H==0?f(t):H==1?sqrt(f(t)):H==2?log(1e3*f(t)+1.)/log(1e3):H==3?asinh(10.*f(t))/3.:v(t);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 s(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}highp float t(highp vec4 v){highp float t=2.*mod(v[0],128.)+step(128.,v[1])-127.;return abs(t+127.)<.001?0.:(1.-step(128.,v[0])*2.)*exp2(t)*((mod(v[1],128.)*65536.+v[2]*256.+v[3]+float(8388608))*exp2(-23.));}vec4 t(float t){float H=s(t*scale+offset);H=mix(H,1.-H,reversed);vec4 m=mix(texture(colormaps,vec2(H,(colormap_id+.5)/num_colormaps)),vec4(0),float(isinf(t)));return f(s(v(vec4(m.xyz+k_brightness,m.w))));}uniform float opacity;void main(){vec3 v=vec3(frag_uv);v.y=1.-v.y;vec4 f=t(t(texture(tex,v).xyzw*255.));out_frag_color=f;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips3d_u8.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler3D;uniform sampler3D tex;in vec3 frag_uv;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}vec4 s(float H){float s=v(H*scale+offset);s=mix(s,1.-s,reversed);vec4 k=mix(texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps)),vec4(0),float(H==blank||isnan(H)));return f(t(v(vec4(k.xyz+k_brightness,k.w))));}uniform float opacity;void main(){vec3 v=vec3(frag_uv);v.y=1.-v.y;vec4 f=s(float(uint(texture(tex,v).x*255.+.5)));out_frag_color=f;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_u8.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;uniform sampler2DArray tex;in vec3 frag_uv_start,frag_uv_end;in float frag_blending_factor;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}vec4 s(float s){float u=v(s*scale+offset);u=mix(u,1.-u,reversed);vec4 H=mix(texture(colormaps,vec2(u,(colormap_id+.5)/num_colormaps)),vec4(0),float(s==blank||isnan(s)));return f(t(v(vec4(H.xyz+k_brightness,H.w))));}vec4 f(vec3 v){return s(float(uint(texture(tex,v).x*255.+.5)));}uniform float opacity;void main(){vec3 v=frag_uv_start,H=frag_uv_end;v.y=1.-v.y;H.y=1.-H.y;vec4 s=f(v),u=f(H);out_frag_color=mix(s,u,frag_blending_factor);out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips3d_i32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler3D;precision lowp isampler3D;precision lowp usampler3D;uniform sampler3D tex;in vec3 frag_uv;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int c(vec4 v){return int(v.x*255.+.5)<<24|int(v.y*255.+.5)<<16|int(v.z*255.+.5)<<8|int(v.w*255.+.5);}vec4 c(float w){float s=v(w*scale+offset);s=mix(s,1.-s,reversed);vec4 k=mix(texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps)),vec4(0),float(w==blank||isnan(w)));return f(t(v(vec4(k.xyz+k_brightness,k.w))));}uniform float opacity;void main(){vec3 v=vec3(frag_uv);v.y=1.-v.y;vec4 f=c(float(c(texture(tex,v).xyzw)));out_frag_color=f;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_u8.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;precision lowp usampler2DArray;precision lowp isampler2DArray;precision mediump int;uniform sampler2DArray tex;in vec3 frag_pos;in vec2 out_clip_pos;out vec4 out_frag_color;struct Tile{int uniq;int texture_idx;float start_time;float empty;};uniform Tile textures_tiles[12];uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float t(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float f(float v){v=t(v);return v*v;}float i(float v){return H==0?t(v):H==1?sqrt(t(v)):H==2?log(1e3*t(v)+1.)/log(1e3):H==3?asinh(10.*t(v))/3.:f(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 i(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 t(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}vec4 v(float v){float r=i(v*scale+offset);r=mix(r,1.-r,reversed);vec4 H=mix(texture(colormaps,vec2(r,(colormap_id+.5)/num_colormaps)),vec4(0),float(v==blank||isnan(v)));return f(i(t(vec4(H.xyz+k_brightness,H.w))));}int f(vec2 v){int H=int(v.y<0.);return int(v.x<0.)+H|H<<1;}float i(vec2 v){float H=atan(abs(v.y),abs(v.x))*1.27323954474;return v.x<0.!=v.y<0.?1.-H:H-1.;}float f(vec3 v){float H=dot(v.xy,v.xy);return H<.1?H*(.5+H*(.125+H*(.0625+H*(.0390625+H*.02734375)))):1.f-v.z;}float i(vec3 v){float H=dot(v.xy,v.xy);return H<.1f?H*(.5+H*(.125+H*(.0625+H*(.0390625+H*.02734375)))):v.z+1.;}int f(int v,int H){v|=H<<2;H=(v^v>>1)&572662306;return v^H^H<<1;}struct HashDxDy{int idx;float dx;float dy;};uniform sampler2D ang2pixd;HashDxDy t(vec3 v){float H=float(1<<0)*.5,r=i(v.xy),t,e;int c=f(v.xy),o=0,u,s;vec2 m=vec2(0);if(v.z>.66666666666){float H=sqrt(3.*f(v));m=vec2(r*H,2.-H);o=c;}else if(v.z<-.66666666666){float H=sqrt(3.*i(v));m=vec2(r*H,H);o=c+8;}else{float H=v.z*1.5;int f=int(r>H),e=int(r>=-H),s=1-e;m=vec2(r-float(f+e-1),H+float(f+s));o=(f+s<<2)+(c+(f&e)&3);}t=H*(m.x+m.y);e=H*(m.y-m.x);u=int(t);s=int(e);return HashDxDy((o<<(0<<1))+f(u,s),t-float(u),e-float(s));}vec3 f(){HashDxDy v=t(normalize(frag_pos).zxy);return vec3(vec2(v.dy,v.dx),float(textures_tiles[v.idx].texture_idx));}void main(){vec3 H=f();H.y=1.-H.y;vec4 i=v(float(uint(texture(tex,H).x*255.+.5)));out_frag_color=i;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_arc.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_arc(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_catalog.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;in vec2 out_uv;in vec3 out_p;out vec4 color;uniform sampler2D kernel_texture;uniform float max_density,fov,strength;void main(){color=texture(kernel_texture,out_uv)/max(log2(fov*1e2),1.);color.x*=strength;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"moc_base.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;layout(location=0)in vec2 lonlat;uniform mat3 u_2world;uniform vec2 ndc_to_clip;uniform float czf;vec2 n(vec3 y){vec2 v=vec2(-y.x,y.y);return y.z>=0.f?v:normalize(v);}vec2 s(vec3 v){float a=length(v.zx),j=sqrt((1.+sqrt(a*(a+v.z)*.5f))*.5f),y=v.y/j,l=0.;if(abs(v.x)<.005){float y=v.x/a;l=-v.x*(1.-y*y/21.)/j;}else j=sqrt((a*a-a*v.z)*2.)/j,l=sign(-v.x)*j;return vec2(l*.5,y)/1.4142135623731;}float n(float v){float j=acos(-1.)*v,a=2.*asin(v);v=a+sin(a)-j;int l=0;for(;abs(v)>125e-10&&l<100;l+=1)a-=v/(1.+cos(a)),v=a+sin(a)-j;return.5*a;}vec2 v(vec3 v){float a=n(v.y);return vec2(atan(-v.x,v.z)*cos(a)/acos(-1.),sin(a));}vec2 t(vec3 v){v.z=max(v.z,.01);return vec2(-v.x,v.y)/(v.z*acos(-1.));}vec3 n(){float v=cos(lonlat.y);return vec3(v*sin(lonlat.x),sin(lonlat.y),v*cos(lonlat.x));}uniform int u_proj;vec2 l(vec3 a){return u_proj==0?t(a):u_proj==1?vec2(-a.x,a.y)/(acos(-1.)*((1.+a.z)*.5)):u_proj==2?n(a):u_proj==3?vec2(-a.x,a.y)*.5/sqrt(.5+.5*a.z):u_proj==4?s(a):u_proj==5?v(a):vec2(atan(-a.x,a.z),atanh(a.y))/acos(-1.);}void main(){gl_Position=vec4(l(u_2world*n())/(ndc_to_clip*czf),0,1);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_mercator.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_mercator(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_backcolor.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision mediump int;layout(location=0)in vec2 pos_clip_space;uniform vec2 ndc_to_clip;uniform float czf;void main(){gl_Position=vec4(pos_clip_space/(ndc_to_clip*czf),0,1);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_i16.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;uniform sampler2DArray tex;in vec3 frag_uv_start,frag_uv_end;in float frag_blending_factor;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int f(vec2 v){int f=int(v.x*255.+.5)<<8|int(v.y*255.+.5);if(f>=32768)f-=65536;return f;}vec4 s(float s){float H=v(s*scale+offset);H=mix(H,1.-H,reversed);vec4 c=mix(texture(colormaps,vec2(H,(colormap_id+.5)/num_colormaps)),vec4(0),float(s==blank||isnan(s)));return f(t(v(vec4(c.xyz+k_brightness,c.w))));}vec4 f(vec3 v){return s(float(f(texture(tex,v).xy)));}uniform float opacity;void main(){vec3 v=frag_uv_start,H=frag_uv_end;v.y=1.-v.y;H.y=1.-H.y;vec4 s=f(v),t=f(H);out_frag_color=mix(s,t,frag_blending_factor);out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_i16.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;precision mediump int;uniform sampler2DArray tex;in vec3 frag_pos;in vec2 out_clip_pos;out vec4 out_frag_color;struct Tile{int uniq;int texture_idx;float start_time;float empty;};uniform Tile textures_tiles[12];uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float t(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float f(float v){v=t(v);return v*v;}float i(float v){return H==0?t(v):H==1?sqrt(t(v)):H==2?log(1e3*t(v)+1.)/log(1e3):H==3?asinh(10.*t(v))/3.:f(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 i(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 t(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int f(vec2 v){int f=int(v.x*255.+.5)<<8|int(v.y*255.+.5);if(f>=32768)f-=65536;return f;}vec4 v(float v){float r=i(v*scale+offset);r=mix(r,1.-r,reversed);vec4 H=mix(texture(colormaps,vec2(r,(colormap_id+.5)/num_colormaps)),vec4(0),float(v==blank||isnan(v)));return f(i(t(vec4(H.xyz+k_brightness,H.w))));}int i(vec2 v){int f=int(v.y<0.);return int(v.x<0.)+f|f<<1;}float t(vec2 v){float f=atan(abs(v.y),abs(v.x))*1.27323954474;return v.x<0.!=v.y<0.?1.-f:f-1.;}float f(vec3 v){float f=dot(v.xy,v.xy);return f<.1?f*(.5+f*(.125+f*(.0625+f*(.0390625+f*.02734375)))):1.f-v.z;}float i(vec3 v){float f=dot(v.xy,v.xy);return f<.1f?f*(.5+f*(.125+f*(.0625+f*(.0390625+f*.02734375)))):v.z+1.;}int f(int v,int f){v|=f<<2;f=(v^v>>1)&572662306;return v^f^f<<1;}struct HashDxDy{int idx;float dx;float dy;};uniform sampler2D ang2pixd;HashDxDy t(vec3 v){float H=float(1<<0)*.5,r=t(v.xy),e,a;int s=i(v.xy),u=0,x,m;vec2 o=vec2(0);if(v.z>.66666666666){float H=sqrt(3.*f(v));o=vec2(r*H,2.-H);u=s;}else if(v.z<-.66666666666){float f=sqrt(3.*i(v));o=vec2(r*f,f);u=s+8;}else{float f=v.z*1.5;int H=int(r>f),e=int(r>=-f),x=1-e;o=vec2(r-float(H+e-1),f+float(H+x));u=(H+x<<2)+(s+(H&e)&3);}e=H*(o.x+o.y);a=H*(o.y-o.x);x=int(e);m=int(a);return HashDxDy((u<<(0<<1))+f(x,m),e-float(x),a-float(m));}vec3 f(){HashDxDy v=t(normalize(frag_pos).zxy);return vec3(vec2(v.dy,v.dx),float(textures_tiles[v.idx].texture_idx));}void main(){vec3 H=f();H.y=1.-H.y;vec4 i=v(float(f(texture(tex,H).xy)));out_frag_color=i;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_rgba.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;precision mediump int;uniform sampler2DArray tex;in vec2 out_clip_pos;in vec3 frag_pos;out vec4 out_frag_color;struct Tile{int uniq;int texture_idx;float start_time;float empty;};uniform Tile textures_tiles[12];uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float v(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float t(float f){f=v(f);return f*f;}float f(float f){return H==0?v(f):H==1?sqrt(v(f)):H==2?log(1e3*v(f)+1.)/log(1e3):H==3?asinh(10.*v(f))/3.:t(f);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 f){return vec4(pow(f.x,k_gamma),pow(f.y,k_gamma),pow(f.z,k_gamma),f.w);}vec4 t(vec4 f){return vec4(mix(vec3(dot(f.xyz,vec3(.2126,.7152,.0722))),f.xyz,1.+k_saturation),f.w);}vec4 v(vec4 f){return vec4(.5+(1.+k_contrast)*(f.xyz-.5),f.w);}vec4 f(vec3 i){vec4 r=texture(tex,i).xyzw;r.x=f(r.x);r.y=f(r.y);r.z=f(r.z);r.xyz=mix(r.xyz,1.-r.xyz,reversed);return f(t(v(vec4(r.xyz+k_brightness,r.w))));}int f(vec2 f){int v=int(f.y<0.);return int(f.x<0.)+v|v<<1;}float t(vec2 f){float v=atan(abs(f.y),abs(f.x))*1.27323954474;return f.x<0.!=f.y<0.?1.-v:v-1.;}float t(vec3 f){float v=dot(f.xy,f.xy);return v<.1?v*(.5+v*(.125+v*(.0625+v*(.0390625+v*.02734375)))):1.f-f.z;}float v(vec3 f){float v=dot(f.xy,f.xy);return v<.1f?v*(.5+v*(.125+v*(.0625+v*(.0390625+v*.02734375)))):f.z+1.;}int f(int f,int v){f|=v<<2;v=(f^f>>1)&572662306;return f^v^v<<1;}struct HashDxDy{int idx;float dx;float dy;};uniform sampler2D ang2pixd;HashDxDy i(vec3 i){float H=float(1<<0)*.5,r=t(i.xy),e,a;int n=f(i.xy),u=0,x,o;vec2 s=vec2(0);if(i.z>.66666666666){float f=sqrt(3.*t(i));s=vec2(r*f,2.-f);u=n;}else if(i.z<-.66666666666){float f=sqrt(3.*v(i));s=vec2(r*f,f);u=n+8;}else{float f=i.z*1.5;int v=int(r>f),x=int(r>=-f),a=1-x;s=vec2(r-float(v+x-1),f+float(v+a));u=(v+a<<2)+(n+(v&x)&3);}e=H*(s.x+s.y);a=H*(s.y-s.x);x=int(e);o=int(a);return HashDxDy((u<<(0<<1))+f(x,o),e-float(x),a-float(o));}vec3 f(){HashDxDy f=i(normalize(frag_pos).zxy);return vec3(vec2(f.dy,f.dx),float(textures_tiles[f.idx].texture_idx));}uniform float opacity;uniform vec4 no_tile_color;void main(){vec3 v=f();vec4 r=f(v);out_frag_color=r;out_frag_color=vec4(r.xyz,opacity*r.w);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_ortho.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_orthographic(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"image_sampler.frag",
|
||||
r#"#version 300 es
|
||||
precision highp float;precision highp sampler2D;out vec4 out_frag_color;in vec2 frag_uv;uniform sampler2D tex;uniform float opacity;void main(){out_frag_color=texture(tex,frag_uv);out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"line_inst_ndc.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;layout(location=0)in vec2 p_a;layout(location=1)in vec2 p_b;layout(location=2)in vec2 vertex;out vec2 l;uniform float u_width,u_height,u_thickness;void main(){vec2 v=p_b-p_a;gl_Position=vec4(p_a+v*vertex.x+(u_thickness+2.)*normalize(vec2(-v.y,v))*vertex.y*vec2(1,u_width/u_height)*(2./u_width),0,1);l=vec2(0,vertex.y);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"line_base.frag",
|
||||
r#"#version 300 es
|
||||
precision highp float;out vec4 color;in vec2 l;uniform vec4 u_color;uniform float u_thickness,u_width,u_height;void main(){if(l.x>.05)discard;else{color=u_color;float u=(u_thickness+2.)*.5;color.w=color.w*(1.-smoothstep(u-1.,u,abs((u_thickness+2.)*l.y)));}}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips3d_raster.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 lonlat;layout(location=1)in vec3 uv;out vec3 frag_uv;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;vec2 n(vec3 v){vec2 l=vec2(-v.x,v.y);return v.z>=0.f?l:normalize(l);}vec2 s(vec3 v){float l=length(v.zx),j=sqrt((1.+sqrt(l*(l+v.z)*.5f))*.5f),y=v.y/j,a=0.;if(abs(v.x)<.005){float n=v.x/l;a=-v.x*(1.-n*n/21.)/j;}else j=sqrt((l*l-l*v.z)*2.)/j,a=sign(-v.x)*j;return vec2(a*.5,y)/1.4142135623731;}float n(float v){float j=acos(-1.)*v,l=2.*asin(v);v=l+sin(l)-j;int n=0;for(;abs(v)>125e-10&&n<100;n+=1)l-=v/(1.+cos(l)),v=l+sin(l)-j;return.5*l;}vec2 v(vec3 v){float l=n(v.y);return vec2(atan(-v.x,v.z)*cos(l)/acos(-1.),sin(l));}vec2 t(vec3 v){v.z=max(v.z,.01);return vec2(-v.x,v.y)/(v.z*acos(-1.));}vec3 n(){float v=cos(lonlat.y);return vec3(v*sin(lonlat.x),sin(lonlat.y),v*cos(lonlat.x));}uniform int u_proj;vec2 l(vec3 l){return u_proj==0?t(l):u_proj==1?vec2(-l.x,l.y)/(acos(-1.)*((1.+l.z)*.5)):u_proj==2?n(l):u_proj==3?vec2(-l.x,l.y)*.5/sqrt(.5+.5*l.z):u_proj==4?s(l):u_proj==5?v(l):vec2(atan(-l.x,l.z),atanh(l.y))/acos(-1.);}void main(){gl_Position=vec4(l((inv_model*n()).xyz)/(ndc_to_clip*czf),0,1);frag_uv=uv;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_rgba2cmap.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;precision lowp sampler2DArray;precision lowp isampler2DArray;precision mediump int;in vec3 frag_pos;in vec2 out_clip_pos;out vec4 out_frag_color;struct Tile{int uniq;int texture_idx;float start_time;float empty;};uniform Tile textures_tiles[12];uniform float opacity;uniform sampler2DArray tex;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float t(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float f(float v){v=t(v);return v*v;}float v(float v){return H==0?t(v):H==1?sqrt(t(v)):H==2?log(1e3*t(v)+1.)/log(1e3):H==3?asinh(10.*t(v))/3.:f(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}vec4 f(vec3 s){vec4 i=texture(colormaps,vec2(v(texture(tex,s).x),(colormap_id+.5)/num_colormaps));i.xyz=mix(i.xyz,1.-i.xyz,reversed);return f(t(v(vec4(i.xyz+k_brightness,i.w))));}int f(vec2 v){int f=int(v.y<0.);return int(v.x<0.)+f|f<<1;}float t(vec2 v){float f=atan(abs(v.y),abs(v.x))*1.27323954474;return v.x<0.!=v.y<0.?1.-f:f-1.;}float t(vec3 v){float f=dot(v.xy,v.xy);return f<.1?f*(.5+f*(.125+f*(.0625+f*(.0390625+f*.02734375)))):1.f-v.z;}float v(vec3 v){float f=dot(v.xy,v.xy);return f<.1f?f*(.5+f*(.125+f*(.0625+f*(.0390625+f*.02734375)))):v.z+1.;}int f(int v,int f){v|=f<<2;f=(v^v>>1)&572662306;return v^f^f<<1;}struct HashDxDy{int idx;float dx;float dy;};uniform sampler2D ang2pixd;HashDxDy i(vec3 i){float H=float(1<<0)*.5,a=t(i.xy),e,r;int s=f(i.xy),u=0,m,x;vec2 o=vec2(0);if(i.z>.66666666666){float v=sqrt(3.*t(i));o=vec2(a*v,2.-v);u=s;}else if(i.z<-.66666666666){float f=sqrt(3.*v(i));o=vec2(a*f,f);u=s+8;}else{float v=i.z*1.5;int f=int(a>v),x=int(a>=-v),e=1-x;o=vec2(a-float(f+x-1),v+float(f+e));u=(f+e<<2)+(s+(f&x)&3);}e=H*(o.x+o.y);r=H*(o.y-o.x);m=int(e);x=int(r);return HashDxDy((u<<(0<<1))+f(m,x),e-float(m),r-float(x));}vec3 f(){HashDxDy v=i(normalize(frag_pos).zxy);return vec3(vec2(v.dy,v.dx),float(textures_tiles[v.idx].texture_idx));}void main(){vec3 v=f();out_frag_color=f(v);out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_backcolor.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision mediump int;out vec4 out_frag_color;uniform vec3 color;void main(){out_frag_color=vec4(color,1);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_rgba2cmap.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;uniform sampler2DArray tex;in vec3 frag_uv_start,frag_uv_end;in float frag_blending_factor;out vec4 out_frag_color;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float v(float v){v=f(v);return v*v;}float t(float t){return H==0?f(t):H==1?sqrt(f(t)):H==2?log(1e3*f(t)+1.)/log(1e3):H==3?asinh(10.*f(t))/3.:v(t);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 f){return vec4(pow(f.x,k_gamma),pow(f.y,k_gamma),pow(f.z,k_gamma),f.w);}vec4 t(vec4 f){return vec4(mix(vec3(dot(f.xyz,vec3(.2126,.7152,.0722))),f.xyz,1.+k_saturation),f.w);}vec4 v(vec4 f){return vec4(.5+(1.+k_contrast)*(f.xyz-.5),f.w);}vec4 f(vec3 a){vec4 m=texture(colormaps,vec2(t(texture(tex,a).x),(colormap_id+.5)/num_colormaps));m.xyz=mix(m.xyz,1.-m.xyz,reversed);return f(t(v(vec4(m.xyz+k_brightness,m.w))));}void main(){out_frag_color=mix(f(frag_uv_start),f(frag_uv_end),frag_blending_factor);out_frag_color.w=opacity*out_frag_color.w;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_healpix.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_healpix(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_f32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;uniform sampler2DArray tex;in vec3 frag_uv_start,frag_uv_end;in float frag_blending_factor;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float v(float v){v=f(v);return v*v;}float s(float t){return H==0?f(t):H==1?sqrt(f(t)):H==2?log(1e3*f(t)+1.)/log(1e3):H==3?asinh(10.*f(t))/3.:v(t);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 f){return vec4(pow(f.x,k_gamma),pow(f.y,k_gamma),pow(f.z,k_gamma),f.w);}vec4 s(vec4 f){return vec4(mix(vec3(dot(f.xyz,vec3(.2126,.7152,.0722))),f.xyz,1.+k_saturation),f.w);}vec4 v(vec4 f){return vec4(.5+(1.+k_contrast)*(f.xyz-.5),f.w);}highp float t(highp vec4 f){highp float t=2.*mod(f[0],128.)+step(128.,f[1])-127.;return abs(t+127.)<.001?0.:(1.-step(128.,f[0])*2.)*exp2(t)*((mod(f[1],128.)*65536.+f[2]*256.+f[3]+float(8388608))*exp2(-23.));}vec4 t(float t){float H=s(t*scale+offset);H=mix(H,1.-H,reversed);vec4 m=mix(texture(colormaps,vec2(H,(colormap_id+.5)/num_colormaps)),vec4(0),float(isinf(t)));return f(s(v(vec4(m.xyz+k_brightness,m.w))));}vec4 f(vec3 f){return t(t(texture(tex,f).xyzw*255.));}uniform float opacity;void main(){vec3 t=frag_uv_start,v=frag_uv_end;t.y=1.-t.y;v.y=1.-v.y;vec4 H=f(t),m=f(v);out_frag_color=mix(H,m,frag_blending_factor);out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"colormaps_colormap.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2D;in vec2 out_uv;out vec4 color;uniform sampler2D texture_fbo;uniform float alpha;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;void main(){float s=texture(texture_fbo,out_uv).x;color=texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps));color.w=smoothstep(0.,.1,s)*alpha;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips3d_i16.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler3D;precision lowp isampler3D;precision lowp usampler3D;uniform sampler3D tex;in vec3 frag_uv;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int f(vec2 v){int f=int(v.x*255.+.5)<<8|int(v.y*255.+.5);if(f>=32768)f-=65536;return f;}vec4 l(float H){float s=v(H*scale+offset);s=mix(s,1.-s,reversed);vec4 k=mix(texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps)),vec4(0),float(H==blank||isnan(H)));return f(t(v(vec4(k.xyz+k_brightness,k.w))));}uniform float opacity;void main(){vec3 v=vec3(frag_uv);v.y=1.-v.y;vec4 H=l(float(f(texture(tex,v).xy)));out_frag_color=H;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"fits_base.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;precision highp int;layout(location=0)in vec2 ndc_pos;layout(location=1)in vec2 uv;out vec2 frag_uv;void main(){gl_Position=vec4(ndc_pos,0,1);frag_uv=uv;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"line_base.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;layout(location=0)in vec2 ndc_pos;out float l;void main(){gl_Position=vec4(ndc_pos,0,1);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_raster.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;layout(location=0)in vec3 xyz;layout(location=1)in vec3 uv_start;layout(location=2)in vec3 uv_end;layout(location=3)in float time_tile_received;out vec3 frag_uv_start,frag_uv_end;out float frag_blending_factor;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf,current_time;vec2 n(vec3 f){vec2 v=vec2(-f.x,f.y);return f.z>=0.f?v:normalize(v);}vec2 v(vec3 v){float f=length(v.zx),n=sqrt((1.+sqrt(f*(f+v.z)*.5f))*.5f),z=v.y/n,l=0.;if(abs(v.x)<.005){float t=v.x/f;l=-v.x*(1.-t*t/21.)/n;}else n=sqrt((f*f-f*v.z)*2.)/n,l=sign(-v.x)*n;return vec2(l*.5,z)/1.4142135623731;}float n(float v){float f=acos(-1.)*v,z=2.*asin(v);v=z+sin(z)-f;int n=0;for(;abs(v)>125e-10&&n<100;n+=1)z-=v/(1.+cos(z)),v=z+sin(z)-f;return.5*z;}vec2 s(vec3 v){float f=n(v.y);return vec2(atan(-v.x,v.z)*cos(f)/acos(-1.),sin(f));}vec2 t(vec3 v){v.z=max(v.z,.01);return vec2(-v.x,v.y)/(v.z*acos(-1.));}uniform int u_proj;vec2 n(){vec3 f=inv_model*xyz;return u_proj==0?t(f):u_proj==1?vec2(-f.x,f.y)/(acos(-1.)*((1.+f.z)*.5)):u_proj==2?n(f):u_proj==3?vec2(-f.x,f.y)*.5/sqrt(.5+.5*f.z):u_proj==4?v(f):u_proj==5?s(f):vec2(atan(-f.x,f.z),atanh(f.y))/acos(-1.);}void main(){gl_Position=vec4(n()/(ndc_to_clip*czf),0,1);frag_uv_start=uv_start;frag_uv_end=uv_end;frag_blending_factor=min((current_time-time_tile_received)/2e2,1.);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_i32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;precision lowp usampler2DArray;precision lowp isampler2DArray;precision mediump int;uniform sampler2DArray tex;in vec3 frag_pos;in vec2 out_clip_pos;out vec4 out_frag_color;struct Tile{int uniq;int texture_idx;float start_time;float empty;};uniform Tile textures_tiles[12];uniform float opacity;int t(vec2 v){int i=int(v.y<0.);return int(v.x<0.)+i|i<<1;}float i(vec2 v){float f=atan(abs(v.y),abs(v.x))*1.27323954474;return v.x<0.!=v.y<0.?1.-f:f-1.;}float i(vec3 v){float i=dot(v.xy,v.xy);return i<.1?i*(.5+i*(.125+i*(.0625+i*(.0390625+i*.02734375)))):1.f-v.z;}float t(vec3 v){float i=dot(v.xy,v.xy);return i<.1f?i*(.5+i*(.125+i*(.0625+i*(.0390625+i*.02734375)))):v.z+1.;}int i(int v,int i){v|=i<<2;i=(v^v>>1)&572662306;return v^i^i<<1;}struct HashDxDy{int idx;float dx;float dy;};uniform sampler2D ang2pixd;HashDxDy v(vec3 v){float f=float(1<<0)*.5,H=i(v.xy),e,r;int c=t(v.xy),o=0,u,s;vec2 m=vec2(0);if(v.z>.66666666666){float f=sqrt(3.*i(v));m=vec2(H*f,2.-f);o=c;}else if(v.z<-.66666666666){float i=sqrt(3.*t(v));m=vec2(H*i,i);o=c+8;}else{float i=v.z*1.5;int f=int(H>i),e=int(H>=-i),s=1-e;m=vec2(H-float(f+e-1),i+float(f+s));o=(f+s<<2)+(c+(f&e)&3);}e=f*(m.x+m.y);r=f*(m.y-m.x);u=int(e);s=int(r);return HashDxDy((o<<(0<<1))+i(u,s),e-float(u),r-float(s));}vec3 i(){HashDxDy f=v(normalize(frag_pos).zxy);return vec3(vec2(f.dy,f.dx),float(textures_tiles[f.idx].texture_idx));}uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float i(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=i(v);return v*v;}float v(float v){return H==0?i(v):H==1?sqrt(i(v)):H==2?log(1e3*i(v)+1.)/log(1e3):H==3?asinh(10.*i(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 i(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int f(vec4 v){return int(v.x*255.+.5)<<24|int(v.y*255.+.5)<<16|int(v.z*255.+.5)<<8|int(v.w*255.+.5);}vec4 f(float f){float m=v(f*scale+offset);m=mix(m,1.-m,reversed);vec4 H=mix(texture(colormaps,vec2(m,(colormap_id+.5)/num_colormaps)),vec4(0),float(f==blank||isnan(f)));return i(t(v(vec4(H.xyz+k_brightness,H.w))));}void main(){vec3 v=i();v.y=1.-v.y;vec4 H=f(float(f(texture(tex,v).xyzw)));out_frag_color=H;out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_tan.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_gnomonic(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"fits_i32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2D;precision mediump int;out vec4 out_frag_color;in vec2 frag_uv;uniform sampler2D tex;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float t(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float f(float v){v=t(v);return v*v;}float v(float v){return H==0?t(v):H==1?sqrt(t(v)):H==2?log(1e3*t(v)+1.)/log(1e3):H==3?asinh(10.*t(v))/3.:f(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int c(vec4 v){return int(v.x*255.+.5)<<24|int(v.y*255.+.5)<<16|int(v.z*255.+.5)<<8|int(v.w*255.+.5);}vec4 c(float H){float s=v(H*scale+offset);s=mix(s,1.-s,reversed);vec4 k=mix(texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps)),vec4(0),float(H==blank||isnan(H)));return f(t(v(vec4(k.xyz+k_brightness,k.w))));}void main(){out_frag_color=c(float(c(texture(tex,frag_uv).xyzw)));out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips3d_red.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler3D;precision lowp isampler3D;precision lowp usampler3D;uniform sampler3D tex;in vec3 frag_uv;out vec4 out_frag_color;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float v(float v){return clamp((v-min_value)/(max_value-min_value),0.,1.);}float f(float f){f=v(f);return f*f;}float t(float c){return H==0?v(c):H==1?sqrt(v(c)):H==2?log(1e3*v(c)+1.)/log(1e3):H==3?asinh(10.*v(c))/3.:f(c);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}vec4 f(){vec2 c=texture(tex,vec3(frag_uv)).xy;c.x=t(c.x);c.x=mix(c.x,1.-c.x,reversed);vec3 s=texture(colormaps,vec2(c.x,(colormap_id+.5)/num_colormaps)).xyz;return f(t(v(vec4(vec4(s,c.y).xyz+k_brightness,vec4(s,c.y).w))));}void main(){out_frag_color=f();out_frag_color.w=opacity*out_frag_color.w;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"fits_i16.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2D;precision mediump int;out vec4 out_frag_color;in vec2 frag_uv;uniform sampler2D tex;uniform float opacity,scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int f(vec2 v){int f=int(v.x*255.+.5)<<8|int(v.y*255.+.5);if(f>=32768)f-=65536;return f;}vec4 m(float H){float m=v(H*scale+offset);m=mix(m,1.-m,reversed);vec4 k=mix(texture(colormaps,vec2(m,(colormap_id+.5)/num_colormaps)),vec4(0),float(H==blank||isnan(H)));return f(t(v(vec4(k.xyz+k_brightness,k.w))));}void main(){out_frag_color=m(float(f(texture(tex,frag_uv).xy)));out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_mollweide.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_mollweide(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"passes_post_vertex_100es.vert",
|
||||
r#"#version 300 es
|
||||
precision mediump float;layout(location=0)in vec2 a_pos;out vec2 v_tc;void main(){gl_Position=vec4(a_pos*2.-1.,0,1);v_tc=a_pos;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"line_inst_lonlat.vert",
|
||||
r#"#version 300 es
|
||||
precision highp float;layout(location=0)in vec2 p_a_lonlat;layout(location=1)in vec2 p_b_lonlat;layout(location=2)in vec2 vertex;uniform mat3 u_2world;uniform vec2 ndc_to_clip;uniform float czf,u_width,u_height,u_thickness;out vec2 l;vec2 v(vec3 v){vec2 n=vec2(-v.x,v.y);return v.z>=0.f?n:normalize(n);}vec2 n(vec3 v){float n=length(v.zx),u=sqrt((1.+sqrt(n*(n+v.z)*.5f))*.5f),y=v.y/u,l=0.;if(abs(v.x)<.005){float c=v.x/n;l=-v.x*(1.-c*c/21.)/u;}else u=sqrt((n*n-n*v.z)*2.)/u,l=sign(-v.x)*u;return vec2(l*.5,y)/1.4142135623731;}float n(float v){float n=acos(-1.)*v,u=2.*asin(v);v=u+sin(u)-n;int l=0;for(;abs(v)>125e-10&&l<100;l+=1)u-=v/(1.+cos(u)),v=u+sin(u)-n;return.5*u;}vec2 s(vec3 v){float u=n(v.y);return vec2(atan(-v.x,v.z)*cos(u)/acos(-1.),sin(u));}vec2 t(vec3 v){v.z=max(v.z,.01);return vec2(-v.x,v.y)/(v.z*acos(-1.));}vec3 n(vec2 v){float u=cos(v.y);return vec3(u*sin(v.x),sin(v.y),u*cos(v.x));}uniform int u_proj;vec2 e(vec3 u){return u_proj==0?t(u):u_proj==1?vec2(-u.x,u.y)/(acos(-1.)*((1.+u.z)*.5)):u_proj==2?v(u):u_proj==3?vec2(-u.x,u.y)*.5/sqrt(.5+.5*u.z):u_proj==4?n(u):u_proj==5?s(u):vec2(atan(-u.x,u.z),atanh(u.y))/acos(-1.);}void main(){vec2 v=e(u_2world*n(p_a_lonlat)),u=e(u_2world*n(p_b_lonlat)),y=v-u,j=v/(ndc_to_clip*czf);v=u/(ndc_to_clip*czf)-j;gl_Position=vec4(j+v*vertex.x+(u_thickness+2.)*normalize(vec2(-v.y,v))*vertex.y*vec2(1,u_width/u_height)*(2./u_width),0,1);l=vec2(dot(y,y),vertex.y);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_rasterizer_i32.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2DArray;uniform sampler2DArray tex;in vec3 frag_uv_start,frag_uv_end;in float frag_blending_factor;out vec4 out_frag_color;uniform float scale,offset,blank,min_value,max_value;uniform int H;uniform float reversed;uniform sampler2D colormaps;uniform float num_colormaps,colormap_id;float f(float f){return clamp((f-min_value)/(max_value-min_value),0.,1.);}float t(float v){v=f(v);return v*v;}float v(float v){return H==0?f(v):H==1?sqrt(f(v)):H==2?log(1e3*f(v)+1.)/log(1e3):H==3?asinh(10.*f(v))/3.:t(v);}uniform float k_gamma,k_saturation,k_contrast,k_brightness,k_exposure;vec4 f(vec4 v){return vec4(pow(v.x,k_gamma),pow(v.y,k_gamma),pow(v.z,k_gamma),v.w);}vec4 t(vec4 v){return vec4(mix(vec3(dot(v.xyz,vec3(.2126,.7152,.0722))),v.xyz,1.+k_saturation),v.w);}vec4 v(vec4 v){return vec4(.5+(1.+k_contrast)*(v.xyz-.5),v.w);}int c(vec4 v){return int(v.x*255.+.5)<<24|int(v.y*255.+.5)<<16|int(v.z*255.+.5)<<8|int(v.w*255.+.5);}vec4 c(float H){float s=v(H*scale+offset);s=mix(s,1.-s,reversed);vec4 c=mix(texture(colormaps,vec2(s,(colormap_id+.5)/num_colormaps)),vec4(0),float(H==blank||isnan(H)));return f(t(v(vec4(c.xyz+k_brightness,c.w))));}vec4 c(vec3 v){return c(float(c(texture(tex,v).xyzw)));}uniform float opacity;void main(){vec3 v=frag_uv_start,f=frag_uv_end;v.y=1.-v.y;f.y=1.-f.y;vec4 H=c(v),t=c(f);out_frag_color=mix(H,t,frag_blending_factor);out_frag_color.w=out_frag_color.w*opacity;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"hips_raytracer_raytracer.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision mediump int;layout(location=0)in vec2 pos_clip_space;layout(location=1)in vec3 pos_world_space;out vec2 out_clip_pos;out vec3 frag_pos;uniform vec2 ndc_to_clip;uniform float czf;uniform mat3 model;void main(){frag_pos=model*pos_world_space;gl_Position=vec4(pos_clip_space/(ndc_to_clip*czf),0,1);out_clip_pos=pos_clip_space;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"passes_post_fragment_100es.frag",
|
||||
r#"#version 300 es
|
||||
precision mediump float;in vec2 v_tc;out vec4 color;uniform sampler2D fbo_tex;void main(){color=texture(fbo_tex,v_tc);}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_ortho.frag",
|
||||
r#"#version 300 es
|
||||
precision lowp float;in vec2 out_uv;in vec3 out_p;out vec4 color;uniform sampler2D kernel_texture;uniform float max_density,fov,strength;void main(){if(out_p.z<0.f)discard;color=texture(kernel_texture,out_uv)/max(log2(fov*1e2),1.);color.x*=strength;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"catalogs_aitoff.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;layout(location=0)in vec2 offset;layout(location=1)in vec2 uv;layout(location=2)in vec3 center;uniform float current_time;uniform mat3 inv_model;uniform vec2 ndc_to_clip;uniform float czf;uniform vec2 kernel_size;out vec2 out_uv;out vec3 out_p;uniform int u_proj;void main(){vec3 v=inv_model*center;vec2 n=world2clip_aitoff(v);gl_Position=vec4(n/(ndc_to_clip*czf)+offset*kernel_size,0,1);out_uv=uv;out_p=v;}"#,
|
||||
);
|
||||
out.insert(
|
||||
r"colormaps_colormap.vert",
|
||||
r#"#version 300 es
|
||||
precision lowp float;precision lowp sampler2D;layout(location=0)in vec2 position;layout(location=1)in vec2 uv;out vec2 out_uv;void main(){gl_Position=vec4(position,0,1);out_uv=uv;}"#,
|
||||
);
|
||||
out
|
||||
}
|
||||
@@ -69,6 +69,7 @@ impl HiPSLocalFiles {
|
||||
ImageExt::Jpeg => &self.tiles[1],
|
||||
ImageExt::Png => &self.tiles[2],
|
||||
ImageExt::Webp => &self.tiles[3],
|
||||
ImageExt::FitsFz => todo!(),
|
||||
};
|
||||
|
||||
tiles_per_fmt[d].get(&i)
|
||||
|
||||
@@ -50,15 +50,9 @@ pub unsafe fn transmute_boxed_slice<I, O>(s: Box<[I]>) -> Box<[O]> {
|
||||
Box::from_raw(out_slice_ptr)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn transmute_vec_to_u8<I>(mut s: Vec<I>) -> Vec<u8> {
|
||||
s.set_len(std::mem::size_of_val(&s[..]));
|
||||
std::mem::transmute(s)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn transmute_vec<I, O>(mut s: Vec<I>) -> Result<Vec<O>, &'static str> {
|
||||
if std::mem::size_of::<I>() % std::mem::size_of::<O>() > 0 {
|
||||
if !std::mem::size_of::<I>().is_multiple_of(std::mem::size_of::<O>()) {
|
||||
Err("The input type is not a multiple of the output type")
|
||||
} else {
|
||||
s.set_len(s.len() * (std::mem::size_of::<I>() / std::mem::size_of::<O>()));
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
/* disable x swipe on chrome, firefox */
|
||||
/* see. https://stackoverflow.com/questions/30636930/disable-web-page-navigation-on-swipeback-and-forward */
|
||||
overscroll-behavior-x: none;
|
||||
overscroll-behavior-y: none; /* Prevents vertical pull-to-refresh */
|
||||
/* Hide the draggable boxes that goes out of the view */
|
||||
overflow: hidden;
|
||||
/* media query on the aladin lite container. not supported everywhere.
|
||||
@@ -1117,6 +1118,14 @@ otherwise it fits its content options. If those are too big the select can go ou
|
||||
left: 0.2rem;
|
||||
}
|
||||
|
||||
.aladin-link {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.aladin-link:hover {
|
||||
color: greenyellow;
|
||||
}
|
||||
|
||||
.aladin-simbadPointer-control {
|
||||
position: absolute;
|
||||
top: 7.8rem;
|
||||
|
||||
@@ -362,7 +362,7 @@ A.graphicOverlay = function (options) {
|
||||
* @returns {ProgressiveCat} Returns a new Overlay object representing the graphic overlay.
|
||||
*
|
||||
* @example
|
||||
* let gaia = A.catalogHiPS('http://axel.u-strasbg.fr/HiPSCatService/I/345/gaia2', {onClick: 'showTable', color: 'orange', name: 'Gaia', filter: myFilterFunction});
|
||||
* let gaia = A.catalogHiPS('http://axel.cds.unistra.fr/HiPSCatService/I/345/gaia2', {onClick: 'showTable', color: 'orange', name: 'Gaia', filter: myFilterFunction});
|
||||
* aladin.addCatalog(gaia)
|
||||
*/
|
||||
A.catalogHiPS = function (url, options) {
|
||||
|
||||
@@ -941,7 +941,7 @@ export let Aladin = (function () {
|
||||
objectName +
|
||||
"'";
|
||||
var url =
|
||||
"//simbad.u-strasbg.fr/simbad/sim-tap/sync?query=" +
|
||||
"//simbad.cds.unistra.fr/simbad/sim-tap/sync?query=" +
|
||||
encodeURIComponent(query) +
|
||||
"&request=doQuery&lang=adql&format=json&phase=run";
|
||||
|
||||
@@ -3117,7 +3117,6 @@ aladin.displayFITS(
|
||||
|
||||
get("https://alasky.unistra.fr/cgi/fits2HiPS", data).then(
|
||||
async (response) => {
|
||||
console.log(response, data)
|
||||
if (response.status != "success") {
|
||||
console.error("An error occured: " + response.message);
|
||||
if (errorCallback) {
|
||||
|
||||
@@ -59,9 +59,9 @@
|
||||
}
|
||||
|
||||
this.maxCut = {
|
||||
webp: 1.0,
|
||||
jpeg: 1.0,
|
||||
png: 1.0,
|
||||
webp: 255.0,
|
||||
jpeg: 255.0,
|
||||
png: 255.0,
|
||||
fits: undefined // wait the default value coming from the properties
|
||||
};
|
||||
if (options && Number.isFinite(options.maxCut)) {
|
||||
@@ -95,6 +95,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
let minCut = this.minCut[this.imgFormat]
|
||||
if (this.imgFormat !== "fits") {
|
||||
minCut /= 255.0
|
||||
}
|
||||
|
||||
let maxCut = this.maxCut[this.imgFormat]
|
||||
if (this.imgFormat !== "fits") {
|
||||
maxCut /= 255.0
|
||||
}
|
||||
|
||||
// Reset the whole meta object
|
||||
return {
|
||||
blendCfg: blend,
|
||||
@@ -107,8 +117,8 @@
|
||||
kContrast: this.kContrast,
|
||||
|
||||
stretch: this.stretch,
|
||||
minCut: this.minCut[this.imgFormat],
|
||||
maxCut: this.maxCut[this.imgFormat],
|
||||
minCut,
|
||||
maxCut,
|
||||
reversed: this.reversed,
|
||||
cmapName: this.colormap,
|
||||
}
|
||||
@@ -121,7 +131,7 @@
|
||||
|
||||
this.setColormap(options.colormap, options)
|
||||
|
||||
this.setCuts(options.minCut, options.maxCut)
|
||||
this.setCuts(options.minCut, options.maxCut, options.cutFormat)
|
||||
|
||||
this.setBrightness(options.brightness)
|
||||
this.setSaturation(options.saturation)
|
||||
@@ -249,18 +259,20 @@
|
||||
};
|
||||
|
||||
// Sets the cuts for the current image format
|
||||
ColorCfg.prototype.setCuts = function(minCut, maxCut) {
|
||||
ColorCfg.prototype.setCuts = function(minCut, maxCut, imgFormat) {
|
||||
imgFormat = imgFormat || this.imgFormat;
|
||||
|
||||
if (minCut instanceof Object) {
|
||||
// Mincut is given in the form of an javascript object with all the formats
|
||||
this.minCut = minCut
|
||||
this.minCut = {...this.minCut, ...minCut};
|
||||
} else if (minCut !== null && minCut !== undefined) {
|
||||
this.minCut[this.imgFormat] = minCut;
|
||||
this.minCut[imgFormat] = minCut;
|
||||
}
|
||||
|
||||
if (maxCut instanceof Object) {
|
||||
this.maxCut = maxCut;
|
||||
this.maxCut = {...this.maxCut, ...maxCut};
|
||||
} else if (maxCut !== null && maxCut !== undefined) {
|
||||
this.maxCut[this.imgFormat] = maxCut;
|
||||
this.maxCut[imgFormat] = maxCut;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ export class PolySelect extends FSM {
|
||||
|
||||
view.aladin.removeStatusBarMessage('selector')
|
||||
}
|
||||
|
||||
let btn;
|
||||
let mouseout = (params) => {
|
||||
let {e, coo} = params;
|
||||
@@ -215,7 +216,7 @@ export class PolySelect extends FSM {
|
||||
};
|
||||
|
||||
let fsm;
|
||||
if (Utils.hasTouchScreen()) {
|
||||
//if (Utils.hasTouchScreen()) {
|
||||
let mousedown = click;
|
||||
let mouseup = click;
|
||||
|
||||
@@ -259,7 +260,7 @@ export class PolySelect extends FSM {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*} else {
|
||||
// desktop, laptops...
|
||||
fsm = {
|
||||
state: 'off',
|
||||
@@ -296,7 +297,7 @@ export class PolySelect extends FSM {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
super(fsm)
|
||||
let self = this;
|
||||
|
||||
@@ -31,7 +31,6 @@ import { HiPSProperties } from "./HiPSProperties.js";
|
||||
import { Aladin } from "./Aladin.js";
|
||||
import { CooFrameEnum } from "./CooFrameEnum.js";
|
||||
import { Utils } from "./Utils"
|
||||
import { SpectraDisplayer } from "./SpectraDisplayer.js";
|
||||
|
||||
let PropertyParser = {};
|
||||
// Utilitary functions for parsing the properties and giving default values
|
||||
@@ -180,13 +179,17 @@ PropertyParser.isPlanetaryBody = function (properties) {
|
||||
* @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 {string} [requestMode='cors'] - Determines how the request will interact with cross-origin resources.
|
||||
* - 'cors' - allow cross-origin requests with proper CORS headers.
|
||||
* - 'no-cors' - send the request without CORS.
|
||||
* - 'same-origin' - only allow requests to the same origin.
|
||||
* @property {string} [requestCredentials='omit'] - Specifies whether to send cookies and HTTP credentials with the request.
|
||||
* - 'omit' - never send credentials.
|
||||
* - 'same-origin' - send only for same-origin requests.
|
||||
* - 'include' - always send, even for cross-origin requests.
|
||||
* <ul>
|
||||
* <li>'cors' - allow cross-origin requests with proper CORS headers.</li>
|
||||
* <li>'no-cors' - send the request without CORS.</li>
|
||||
* <li>'same-origin' - only allow requests to the same origin.</li>
|
||||
* </ul>
|
||||
* @property {string} [requestCredentials='same-origin'] - Specifies whether to send cookies and HTTP credentials with the request.
|
||||
* <ul>
|
||||
* <li>'omit' - never send credentials.</li>
|
||||
* <li>'same-origin' - send only for same-origin requests.</li>
|
||||
* <li>'include' - always send, even for cross-origin requests.</li>
|
||||
* </ul>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -270,7 +273,7 @@ export let HiPS = (function () {
|
||||
this.name = (options && options.name) || id;
|
||||
this.startUrl = options.startUrl;
|
||||
this.requestMode = options && options.requestMode || 'cors';
|
||||
this.requestCredentials = options && options.requestCredentials || 'omit';
|
||||
this.requestCredentials = options && options.requestCredentials || 'same-origin';
|
||||
|
||||
this.slice = 0;
|
||||
|
||||
@@ -729,9 +732,16 @@ export let HiPS = (function () {
|
||||
*
|
||||
* @param {number} minCut - The low cut value to set for the HiPS.
|
||||
* @param {number} maxCut - The high cut value to set for the HiPS.
|
||||
* @param {string} [imgFormat] - The image format for which one wants to set the cuts. By default, the format used is the current imageFormat
|
||||
*/
|
||||
HiPS.prototype.setCuts = function (minCut, maxCut) {
|
||||
this.setOptions({minCut, maxCut})
|
||||
HiPS.prototype.setCuts = function (minCut, maxCut, imgFormat) {
|
||||
imgFormat = imgFormat?.toLowerCase();
|
||||
|
||||
if (imgFormat === "jpg") {
|
||||
imgFormat = "jpeg";
|
||||
}
|
||||
|
||||
this.setOptions({minCut, maxCut, cutFormat: imgFormat})
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -908,7 +918,7 @@ export let HiPS = (function () {
|
||||
imgFormat = "jpeg";
|
||||
}
|
||||
|
||||
if (!["fits", "png", "jpeg", "webp"].includes(imgFormat)) {
|
||||
if (!["fits", "png", "jpeg", "webp", "fits.fz"].includes(imgFormat)) {
|
||||
console.warn('Formats must lie in ["fits", "png", "jpg", "webp"]. imgFormat option property ignored');
|
||||
} else {
|
||||
// Passed the check, we erase the image format with the new one
|
||||
@@ -922,7 +932,7 @@ export let HiPS = (function () {
|
||||
this.imgFormat = imgFormat;
|
||||
|
||||
let [minCut, maxCut] = this.getCuts();
|
||||
if (minCut === undefined && maxCut === undefined && imgFormat === "fits") {
|
||||
if (minCut === undefined && maxCut === undefined && (imgFormat === "fits" || imgFormat === "fits.fz")) {
|
||||
// sets the default cuts parsed from the properties
|
||||
this.setCuts(this.defaultFitsMinCut, this.defaultFitsMaxCut)
|
||||
}
|
||||
|
||||
@@ -402,6 +402,7 @@ export let Image = (function () {
|
||||
|
||||
// Set the automatic computed cuts
|
||||
let [minCut, maxCut] = self.getCuts();
|
||||
|
||||
minCut = minCut || imageParams.min_cut;
|
||||
maxCut = maxCut || imageParams.max_cut;
|
||||
self.setCuts(
|
||||
|
||||
@@ -60,7 +60,7 @@ export let SimbadPointer = (function() {
|
||||
if (Utils.isNumber(magnitude)) {
|
||||
content += '<em>Mag: </em>' + magnitude + '<br>';
|
||||
}
|
||||
content += '<br><a target="_blank" href="http://cdsportal.u-strasbg.fr/?target=' + encodeURIComponent(objName) + '">Query in CDS portal</a>';
|
||||
content += '<br><a target="_blank" href="http://cdsportal.cds.unistra.fr/?target=' + encodeURIComponent(objName) + '">Query in CDS portal</a>';
|
||||
content += '</div>';
|
||||
|
||||
aladinInstance.showPopup(objCoo.lon, objCoo.lat, title, content);
|
||||
|
||||
@@ -21,7 +21,6 @@ import { ActionButton } from "./gui/Widgets/ActionButton";
|
||||
import { Input } from "./gui/Widgets/Input";
|
||||
import HomeIconUrl from '../../assets/icons/maximize.svg';
|
||||
import SpectraIconUrl from '../../assets/icons/freq.svg';
|
||||
import { ALEvent } from "./events/ALEvent";
|
||||
import { Utils } from "./Utils";
|
||||
import { Aladin } from "./Aladin";
|
||||
|
||||
@@ -142,6 +141,7 @@ export class SpectraDisplayer {
|
||||
this.minY = undefined;
|
||||
this.maxY = undefined;
|
||||
this.mouseFreq = undefined;
|
||||
this.enabled = true;
|
||||
|
||||
// One canvas for the spectra
|
||||
this.canvas = createPlotCanvas("spectra-line");
|
||||
@@ -246,7 +246,7 @@ export class SpectraDisplayer {
|
||||
}
|
||||
|
||||
defineEventListeners() {
|
||||
let lastMouse = { x: 0, y: 0 };
|
||||
this.lastMouse = { x: 0, y: 0 };
|
||||
this.isDragging = false;
|
||||
|
||||
let canvas = this.canvas;
|
||||
@@ -257,32 +257,39 @@ export class SpectraDisplayer {
|
||||
let lastClickTime = 0;
|
||||
const DOUBLE_CLICK_DELAY = 300; // most operating systems uses duration between 250ms and 500ms by default.
|
||||
|
||||
canvas.addEventListener('mousedown', (e) => {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const mx = e.clientX - rect.left;
|
||||
const my = e.clientY - rect.top;
|
||||
|
||||
let mouseDownTime = 0;
|
||||
let mouseDownPos = { x: 0, y: 0 };
|
||||
const CLICK_TIME_THRESHOLD = 250; // ms
|
||||
const CLICK_MOVE_THRESHOLD = 5; // pixels
|
||||
|
||||
|
||||
Utils.on(canvas, 'mousedown touchstart', (e) => {
|
||||
mouseDownTime = Date.now();
|
||||
mouseDownPos = Utils.relMouseCoords(e);
|
||||
|
||||
const mx = mouseDownPos.x;
|
||||
const my = mouseDownPos.y;
|
||||
let v = this.data.values[Math.round(mx / this.scaleX)]
|
||||
|
||||
let len = this.data.values.length;
|
||||
|
||||
v = this.height - (v - this.minY) * this.scaleY
|
||||
if (my >= v) {
|
||||
this.isDragging = true;
|
||||
lastMouse = { x: mx, y: my };
|
||||
this.lastMouse = { x: mx, y: my };
|
||||
canvas.style.cursor = 'grabbing';
|
||||
} else {
|
||||
// check if the click is next to the center bar
|
||||
// Draw the vertical line that can be grabed to move the slice
|
||||
|
||||
this.ctx.beginPath();
|
||||
this.ctx.lineWidth = 30;
|
||||
|
||||
this.ctx.moveTo(this.scaleX * len / 2, this.height);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY - this.minY) * this.scaleY);
|
||||
this.ctx.strokeStyle = Aladin.DEFAULT_OPTIONS.reticleColor;
|
||||
this.ctx.lineWidth = 10;
|
||||
|
||||
if (this.ctx.isPointInStroke(mx, my)) {
|
||||
this.isDragging = true;
|
||||
lastMouse = { x: mx, y: my };
|
||||
this.lastMouse = { x: mx, y: my };
|
||||
canvas.style.cursor = 'grabbing';
|
||||
} else {
|
||||
// propagate event to its sibling
|
||||
@@ -298,9 +305,17 @@ export class SpectraDisplayer {
|
||||
altKey: e.altKey,
|
||||
metaKey: e.metaKey,
|
||||
button: e.button,
|
||||
changedTouches: e.changedTouches,
|
||||
targetTouches: e.targetTouches,
|
||||
relatedTarget: e.relatedTarget,
|
||||
};
|
||||
const event = new MouseEvent('mousedown', paramsEvent);
|
||||
let event;
|
||||
if (e.type === "mousedown") {
|
||||
event = new MouseEvent("mousedown", paramsEvent);
|
||||
} else {
|
||||
this.disableInteraction();
|
||||
event = new TouchEvent("touchstart", paramsEvent)
|
||||
}
|
||||
// Track timing to simulate dblclick
|
||||
const now = Date.now();
|
||||
if (now - lastClickTime < DOUBLE_CLICK_DELAY) {
|
||||
@@ -322,16 +337,43 @@ export class SpectraDisplayer {
|
||||
}
|
||||
});
|
||||
|
||||
canvas.addEventListener('mousemove', (e) => {
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const mx = e.clientX - rect.left;
|
||||
const my = e.clientY - rect.top;
|
||||
Utils.on(canvas, 'mousemove touchmove', (e) => {
|
||||
if (!this.enabled) {
|
||||
let paramsEvent = {
|
||||
bubbles: e.bubbles,
|
||||
cancelable: e.cancelable,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
screenX: e.screenX,
|
||||
screenY: e.screenY,
|
||||
ctrlKey: e.ctrlKey,
|
||||
shiftKey: e.shiftKey,
|
||||
altKey: e.altKey,
|
||||
metaKey: e.metaKey,
|
||||
button: e.button,
|
||||
changedTouches: e.changedTouches,
|
||||
targetTouches: e.targetTouches,
|
||||
relatedTarget: e.relatedTarget,
|
||||
};
|
||||
|
||||
let touchEvent = new TouchEvent("touchmove", paramsEvent);
|
||||
this.view.catalogCanvas.dispatchEvent(touchEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
let mouseXY = Utils.relMouseCoords(e)
|
||||
const mx = mouseXY.x;
|
||||
const my = mouseXY.y;
|
||||
|
||||
// can be in the spectral area
|
||||
let v = this.data.values[Math.round(mx / this.scaleX)]
|
||||
let len = this.data.values.length;
|
||||
|
||||
v = this.height - (v - this.minY) * this.scaleY
|
||||
if (!this.isDragging) {
|
||||
this.isDragging = canvas.style.cursor === 'grabbing';
|
||||
}
|
||||
|
||||
canvas.style.cursor = 'default';
|
||||
|
||||
this.ctxCursor.clearRect(0, 0, this.width, this.height);
|
||||
@@ -363,7 +405,7 @@ export class SpectraDisplayer {
|
||||
this.ctx.moveTo(this.scaleX * len / 2, this.height);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY - this.minY) * this.scaleY);
|
||||
this.ctx.strokeStyle = "red";
|
||||
this.ctx.lineWidth = 10;
|
||||
this.ctx.lineWidth = 30;
|
||||
|
||||
if (this.ctx.isPointInStroke(mx, my)) {
|
||||
this.canvas.style.cursor = 'grab';
|
||||
@@ -372,11 +414,11 @@ export class SpectraDisplayer {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.mouseFreq = null;
|
||||
this.canvas.style.cursor = 'grabbing';
|
||||
|
||||
// is dragged
|
||||
let dx = (mx - lastMouse.x) / this.scaleX;
|
||||
let dx = (mx - this.lastMouse.x) / this.scaleX;
|
||||
if (dx != 0) {
|
||||
// Set the frequency
|
||||
|
||||
@@ -399,29 +441,102 @@ export class SpectraDisplayer {
|
||||
unit: 'Hz'
|
||||
})
|
||||
|
||||
|
||||
lastMouse = { x: mx, y: my };
|
||||
this.lastMouse = { x: mx, y: my };
|
||||
}
|
||||
});
|
||||
|
||||
canvas.addEventListener('mouseup', (e) => {
|
||||
|
||||
Utils.on(canvas, 'mouseup touchend', (e) => {
|
||||
if (!this.enabled) {
|
||||
let paramsEvent = {
|
||||
bubbles: e.bubbles,
|
||||
cancelable: e.cancelable,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
screenX: e.screenX,
|
||||
screenY: e.screenY,
|
||||
ctrlKey: e.ctrlKey,
|
||||
shiftKey: e.shiftKey,
|
||||
altKey: e.altKey,
|
||||
metaKey: e.metaKey,
|
||||
button: e.button,
|
||||
changedTouches: e.changedTouches,
|
||||
targetTouches: e.targetTouches,
|
||||
relatedTarget: e.relatedTarget,
|
||||
};
|
||||
|
||||
let touchEvent = new TouchEvent("touchend", paramsEvent);
|
||||
this.view.catalogCanvas.dispatchEvent(touchEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
this.isDragging = false;
|
||||
canvas.style.cursor = 'default';
|
||||
|
||||
const clickEvent = new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY
|
||||
});
|
||||
this.view.catalogCanvas.dispatchEvent(clickEvent);
|
||||
let mouseXY = Utils.relMouseCoords(e);
|
||||
|
||||
const timeDiff = Date.now() - mouseDownTime;
|
||||
const dx = mouseXY.x - mouseDownPos.x;
|
||||
const dy = mouseXY.y - mouseDownPos.y;
|
||||
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (timeDiff < CLICK_TIME_THRESHOLD && dist < CLICK_MOVE_THRESHOLD) {
|
||||
// Custom click detected
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const mx = mouseXY.x;
|
||||
const my = mouseXY.y;
|
||||
let v = this.data.values[Math.round(mx / this.scaleX)]
|
||||
v = this.height - (v - this.minY) * this.scaleY
|
||||
|
||||
if (my >= v) {
|
||||
let dx = (mx - rect.width * 0.5) / this.scaleX;
|
||||
if (dx != 0) {
|
||||
// Set the frequency
|
||||
|
||||
// look where we are in the freq range
|
||||
let j = Utils.binarySearch(self.data.freqs, self.data.freq);
|
||||
let df, f;
|
||||
if (j > 0 && j < self.data.freqs.length - 1) {
|
||||
df = (self.data.freqs[j + 1] - self.data.freqs[j - 1]) * 0.5;
|
||||
f = self.data.freq + dx * df;
|
||||
} else if (j == 0) {
|
||||
df = self.data.freqs[1] - self.data.freqs[0]
|
||||
f = self.data.freqs[0] + dx * df;
|
||||
} else {
|
||||
df = self.data.freqs[self.data.freqs.length - 1] - self.data.freqs[self.data.freqs.length - 2];
|
||||
f = self.data.freqs[self.data.freqs.length - 1] + dx * df;
|
||||
}
|
||||
|
||||
self.hips.setFrequency({
|
||||
value: f,
|
||||
unit: 'Hz'
|
||||
})
|
||||
}
|
||||
|
||||
this.lastMouse = { x: mx, y: my };
|
||||
}
|
||||
|
||||
//this.ctxCursor.clearRect(0, 0, this.width, this.height);
|
||||
this.mouseFreq = null;
|
||||
}
|
||||
|
||||
|
||||
if (e.type !== "touchend") {
|
||||
const clickEvent = new MouseEvent('click', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY
|
||||
});
|
||||
this.view.catalogCanvas.dispatchEvent(clickEvent);
|
||||
}
|
||||
});
|
||||
|
||||
canvas.addEventListener('mouseout', (e) => {
|
||||
Utils.on(canvas, 'mouseout touchcancel', (e) => {
|
||||
this.isDragging = false;
|
||||
});
|
||||
|
||||
canvas.addEventListener('wheel', (e) => {
|
||||
Utils.on(canvas, 'wheel', (e) => {
|
||||
this.ctxCursor.clearRect(0, 0, this.width, this.height);
|
||||
|
||||
const wheelEvent = new WheelEvent('wheel', {
|
||||
@@ -535,7 +650,7 @@ export class SpectraDisplayer {
|
||||
this._redraw(this.ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
window.addEventListener("spectra", this.spectraUpdateCallback);
|
||||
|
||||
this.resetScale();
|
||||
@@ -550,10 +665,12 @@ export class SpectraDisplayer {
|
||||
}
|
||||
|
||||
enableInteraction() {
|
||||
this.enabled = true;
|
||||
this.divNode.style.pointerEvents = "auto"
|
||||
}
|
||||
|
||||
disableInteraction() {
|
||||
this.enabled = false;
|
||||
this.divNode.style.pointerEvents = "none"
|
||||
}
|
||||
|
||||
@@ -591,6 +708,16 @@ export class SpectraDisplayer {
|
||||
this.ctx.lineWidth = 2;
|
||||
this.ctx.stroke();
|
||||
|
||||
this.ctxCursor.clearRect(0, 0, this.width, this.height);
|
||||
this.ctxCursor.beginPath();
|
||||
this.ctxCursor.moveTo(this.lastMouse.x, this.height);
|
||||
let v = this.data.values[Math.round(this.lastMouse.x / this.scaleX)]
|
||||
v = this.height - (v - this.minY) * this.scaleY
|
||||
this.ctxCursor.lineTo(this.lastMouse.x, v);
|
||||
this.ctxCursor.strokeStyle = "yellow";
|
||||
this.ctxCursor.lineWidth = 2;
|
||||
this.ctxCursor.stroke()
|
||||
|
||||
this._redrawLabels()
|
||||
}
|
||||
|
||||
@@ -703,7 +830,7 @@ export class SpectraDisplayer {
|
||||
|
||||
while (i < i1) {
|
||||
let y;
|
||||
const x = i * this.scaleX;
|
||||
let x = i * this.scaleX;
|
||||
|
||||
const inValidDomain = this.data.freqIdxStart !== undefined && this.data.freqIdxEnd !== undefined && i >= this.data.freqIdxStart && i <= this.data.freqIdxEnd;
|
||||
|
||||
@@ -741,8 +868,6 @@ export class SpectraDisplayer {
|
||||
|
||||
y = this.height - (array[i] - this.minY) * this.scaleY;
|
||||
|
||||
|
||||
|
||||
if (i === 0) {
|
||||
this.ctx.moveTo(x, y);
|
||||
} else {
|
||||
|
||||
@@ -54,7 +54,8 @@ export let URLBuilder = (function() {
|
||||
},
|
||||
|
||||
buildNEDPositionCSURL: function(ra, dec, radiusDegrees) {
|
||||
return 'https://ned.ipac.caltech.edu/cgi-bin/nph-objsearch?search_type=Near+Position+Search&of=xml_main&RA=' + ra + '&DEC=' + dec + '&SR=' + radiusDegrees;
|
||||
//OLD return 'https://ned.ipac.caltech.edu/cgi-bin/nph-objsearch?search_type=Near+Position+Search&of=xml_main&RA=' + ra + '&DEC=' + dec + '&SR=' + radiusDegrees;
|
||||
return 'https://ned.ipac.caltech.edu/tap/sync?query=SELECT+*+FROM+objdir+WHERE+CONTAINS(POINT(\'J2000\',ra,dec),CIRCLE(\'J2000\',' + ra + ',' + dec + ',' + radiusDegrees + '))=1&LANG=ADQL&REQUEST=doQuery&FORMAT=votable'
|
||||
},
|
||||
|
||||
buildNEDObjectCSURL: function(object, radiusDegrees) {
|
||||
|
||||
186
src/js/View.js
@@ -785,17 +785,19 @@ export let View = (function () {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
view.pinchZoomParameters.isPinching = true;
|
||||
view.pinchZoomParameters.initialZoomFactor = view.zoomFactor;
|
||||
view.pinchZoomParameters.initialDistance = Math.sqrt(Math.pow(e.targetTouches[0].clientX - e.targetTouches[1].clientX, 2) + Math.pow(e.targetTouches[0].clientY - e.targetTouches[1].clientY, 2));
|
||||
|
||||
view.fingersRotationParameters.initialViewAngleFromCenter = view.wasm.getViewCenter2NorthPoleAngle();
|
||||
view.fingersRotationParameters.initialViewAngleFromCenter = view.wasm.getRotation();
|
||||
view.fingersRotationParameters.initialFingerAngle = Math.atan2(e.targetTouches[1].clientY - e.targetTouches[0].clientY, e.targetTouches[1].clientX - e.targetTouches[0].clientX) * 180.0 / Math.PI;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
view.dragCoo = xymouse;
|
||||
view.dragPastCoo = xymouse;
|
||||
|
||||
view.dragging = true;
|
||||
|
||||
@@ -816,39 +818,6 @@ export let View = (function () {
|
||||
return true;
|
||||
});
|
||||
|
||||
/*
|
||||
Utils.on(view.catalogCanvas, "mouseup", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const xymouse = Utils.relMouseCoords(e);
|
||||
|
||||
ALEvent.CANVAS_EVENT.dispatchedTo(view.aladinDiv, {
|
||||
state: {
|
||||
mode: view.mode,
|
||||
dragging: view.dragging,
|
||||
rightClickPressed: view.rightClick
|
||||
},
|
||||
xy: xymouse,
|
||||
ev: e,
|
||||
});
|
||||
|
||||
if (view.rightClick) {
|
||||
if (showContextMenu) {
|
||||
view.aladin.contextMenu && view.aladin.contextMenu.show({e});
|
||||
}
|
||||
|
||||
view.rightClick = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.mode === View.SELECT) {
|
||||
view.selector.dispatch('mouseup', {coo: xymouse})
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
Utils.on(view.catalogCanvas, "click", function (e) {
|
||||
// call listener of 'click' event
|
||||
|
||||
@@ -875,6 +844,28 @@ export let View = (function () {
|
||||
|
||||
});
|
||||
|
||||
Utils.on(document, "mouseup touchend", function(e) {
|
||||
var wasDragging = view.realDragging === true;
|
||||
|
||||
if (view.dragging) { // if we were dragging, reset to default cursor
|
||||
if(view.mode === View.PAN) {
|
||||
view.setCursor('default');
|
||||
}
|
||||
|
||||
view.dragging = false;
|
||||
if (wasDragging) {
|
||||
view.realDragging = false;
|
||||
|
||||
// call the positionChanged once more with a dragging = false
|
||||
view.throttledPositionChanged(false);
|
||||
}
|
||||
|
||||
if (view.spectraDisplayer) {
|
||||
view.spectraDisplayer.enableInteraction();
|
||||
}
|
||||
} // end of "if (view.dragging) ... "
|
||||
});
|
||||
|
||||
// reacting on 'click' rather on 'mouseup' is more reliable when panning the view
|
||||
Utils.on(view.catalogCanvas, "mouseup mouseout touchend touchcancel", function (e) {
|
||||
const xymouse = Utils.relMouseCoords(e);
|
||||
@@ -915,26 +906,27 @@ export let View = (function () {
|
||||
|
||||
var wasDragging = view.realDragging === true;
|
||||
|
||||
if (view.dragging) { // if we were dragging, reset to default cursor
|
||||
/*if (view.dragging) { // if we were dragging, reset to default cursor
|
||||
if(view.mode === View.PAN) {
|
||||
view.setCursor('default');
|
||||
}
|
||||
|
||||
view.dragging = false;
|
||||
if (view.spectraDisplayer) {
|
||||
view.spectraDisplayer.enableInteraction();
|
||||
}
|
||||
|
||||
if (wasDragging) {
|
||||
view.realDragging = false;
|
||||
|
||||
// call the positionChanged once more with a dragging = false
|
||||
view.throttledPositionChanged(false);
|
||||
}
|
||||
} // end of "if (view.dragging) ... "
|
||||
|
||||
if (view.spectraDisplayer) {
|
||||
view.spectraDisplayer.enableInteraction();
|
||||
}
|
||||
} // end of "if (view.dragging) ... "*/
|
||||
|
||||
view.mustClearCatalog = true;
|
||||
view.dragCoo = null;
|
||||
view.dragPastCoo = null;
|
||||
|
||||
if (e.type === "mouseup") {
|
||||
if (view.mode === View.SELECT) {
|
||||
@@ -1002,7 +994,9 @@ export let View = (function () {
|
||||
// TODO : remplacer par mecanisme de listeners
|
||||
// on avertit les catalogues progressifs
|
||||
view.refreshProgressiveCats();
|
||||
view.wasm.releaseLeftButtonMouse();
|
||||
if (wasDragging) {
|
||||
view.wasm.releaseLeftButtonMouse();
|
||||
}
|
||||
});
|
||||
|
||||
var lastHoveredObject; // save last object hovered by mouse
|
||||
@@ -1249,32 +1243,39 @@ export let View = (function () {
|
||||
|
||||
view.realDragging = true;
|
||||
|
||||
if (view.mode === View.PAN) {
|
||||
view.pan = {
|
||||
s1: view.dragCoo,
|
||||
s2: xymouse
|
||||
};
|
||||
}
|
||||
|
||||
var s1 = view.dragCoo, s2 = xymouse;
|
||||
// update drag coo with the new position
|
||||
view.dragCoo = xymouse;
|
||||
// update drag coo with the new position
|
||||
|
||||
/*if (view.mode == View.SELECT) {
|
||||
view.requestRedraw();
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (view.mode === View.PAN) {
|
||||
view.wasm.moveMouse(s1.x, s1.y, s2.x, s2.y);
|
||||
view.wasm.goFromTo(s1.x, s1.y, s2.x, s2.y);
|
||||
|
||||
view.updateCenter();
|
||||
|
||||
ALEvent.POSITION_CHANGED.dispatchedTo(view.aladin.aladinDiv, view.viewCenter);
|
||||
|
||||
// Apply position changed callback after the move
|
||||
view.throttledPositionChanged(true);
|
||||
}
|
||||
}); //// endof mousemove ////
|
||||
|
||||
// disable text selection on IE
|
||||
//Utils.on(view.aladinDiv, "selectstart", function () { return false; })
|
||||
|
||||
view.prevWheelTime = undefined;
|
||||
|
||||
function normalizeWheel(event) {
|
||||
// Safari/Chrome on macOS: deltaMode = 0 (pixels), but trackpad steps are tiny
|
||||
let scale = 1;
|
||||
if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
||||
scale = 16; // assume ~16px per line
|
||||
} else if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
||||
scale = window.innerHeight;
|
||||
}
|
||||
return event.deltaY * scale;
|
||||
}
|
||||
view.zoomDelta = 0;
|
||||
|
||||
Utils.on(view.catalogCanvas, 'wheel', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -1295,24 +1296,13 @@ export let View = (function () {
|
||||
if (typeof onWheelTriggeredFunction === 'function') {
|
||||
onWheelTriggeredFunction(e)
|
||||
} else {
|
||||
// Default Aladin Lite zooming
|
||||
view.delta = e.deltaY || e.detail || (-e.wheelDelta);
|
||||
|
||||
if (!view.throttledTouchPadZoom) {
|
||||
view.throttledTouchPadZoom = () => {
|
||||
const factor = Utils.detectTrackPad(e) ? 1.05 : 1.2;
|
||||
const currZoomFactor = view.zoom.isZooming ? view.zoom.finalZoom : view.zoomFactor;
|
||||
let newZoomFactor = view.delta > 0 ? currZoomFactor * factor : currZoomFactor / factor;
|
||||
|
||||
// inside case
|
||||
view.zoom.apply({
|
||||
stop: newZoomFactor,
|
||||
duration: 100,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
view.throttledTouchPadZoom();
|
||||
// Default Aladin Lite zooming
|
||||
const normalizedDelta = e.deltaY && normalizeWheel(e) || e.detail || (-e.wheelDelta);
|
||||
// Accumulate the normalized delta
|
||||
// We do not zoom because we cannot rely on "wheel" event
|
||||
// being triggered at constant time steps
|
||||
// The zoom is delayed to the redraw which is animation frame requested!
|
||||
view.zoomDelta += normalizedDelta;
|
||||
|
||||
if (view.mode === View.TOOL_COLOR_PICKER) {
|
||||
pickColor(xymouse);
|
||||
@@ -1386,17 +1376,44 @@ export let View = (function () {
|
||||
/**
|
||||
* redraw the whole view
|
||||
*/
|
||||
View.prototype.redraw = function (timestamp) {
|
||||
// request another frame
|
||||
requestAnimFrame(this.redrawClbk);
|
||||
|
||||
View.prototype.redraw = function (now) {
|
||||
// Elapsed time since last loop
|
||||
const now = performance.now();
|
||||
const elapsedTime = now - timestamp;
|
||||
this.dt = elapsedTime;
|
||||
const elapsedTime = now - this.prevTime;
|
||||
this.prevTime = now;
|
||||
|
||||
if (Math.abs(this.zoomDelta) > 1e-3) {
|
||||
// Apply a fraction each frame (smoothing)
|
||||
let step = this.zoomDelta * 0.2;
|
||||
function wheelToZoomFactor(delta) {
|
||||
const sensitivity = 0.002; // tune this
|
||||
return Math.exp(-delta * sensitivity);
|
||||
}
|
||||
|
||||
this.zoomFactor /= wheelToZoomFactor(step);
|
||||
this.zoomDelta -= step;
|
||||
}
|
||||
|
||||
if (this.pan) {
|
||||
let s1 = this.pan.s1;
|
||||
let s2 = this.pan.s2;
|
||||
|
||||
if (s1 && s2) {
|
||||
this.wasm.moveMouse(s1.x, s1.y, s2.x, s2.y);
|
||||
this.wasm.goFromTo(s1.x, s1.y, s2.x, s2.y);
|
||||
|
||||
this.updateCenter();
|
||||
|
||||
ALEvent.POSITION_CHANGED.dispatchedTo(this.aladin.aladinDiv, this.viewCenter);
|
||||
|
||||
// Apply position changed callback after the move
|
||||
this.throttledPositionChanged(true);
|
||||
}
|
||||
|
||||
this.pan = null;
|
||||
}
|
||||
|
||||
this.moving = this.wasm.update(elapsedTime);
|
||||
|
||||
|
||||
// inertia run throttled position
|
||||
if (this.moving && this.aladin.callbacksByEventName && this.aladin.callbacksByEventName['positionChanged'] && this.wasm.isInerting()) {
|
||||
// run the trottled position
|
||||
@@ -1409,6 +1426,9 @@ export let View = (function () {
|
||||
this.drawAllOverlays();
|
||||
}
|
||||
this.needRedraw = false;
|
||||
|
||||
// request another frame
|
||||
requestAnimFrame(this.redrawClbk);
|
||||
};
|
||||
|
||||
View.prototype.drawAllOverlays = function () {
|
||||
@@ -1686,6 +1706,10 @@ export let View = (function () {
|
||||
}
|
||||
|
||||
View.prototype.setRotation = function(rotation) {
|
||||
if (Math.abs(rotation - this.aladin.getRotation()) < 1e-5) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.wasm.setRotation(rotation);
|
||||
var rotationChangedCallback = this.aladin.callbacksByEventName["rotationChanged"];
|
||||
typeof rotationChangedCallback === "function" && rotationChangedCallback(rotation);
|
||||
|
||||
@@ -52,19 +52,29 @@ export class HiPSBrowserBox extends Box {
|
||||
|
||||
MocServer.getAllHiPSes().then((HiPSes) => {
|
||||
HiPSBrowserBox.HiPSList = {}
|
||||
|
||||
self.HiPSTree = {};
|
||||
// Fill the HiPSList from the MOCServer
|
||||
|
||||
// Build a hierarchy w.r.t sorted by regime
|
||||
HiPSes.forEach((h) => {
|
||||
let name = h.obs_title;
|
||||
name = name.replace(/:|\'/g, '');
|
||||
HiPSBrowserBox.HiPSList[name] = h;
|
||||
|
||||
self.HiPSTree[h.obs_regime] = self.HiPSTree[h.obs_regime] || {};
|
||||
if (self.HiPSTree[h.obs_regime]) {
|
||||
self.HiPSTree[h.obs_regime][name] = h
|
||||
}
|
||||
});
|
||||
|
||||
console.log("jkjk", self.HiPSTree)
|
||||
|
||||
|
||||
// Initialize the autocompletion without any filtering
|
||||
self._filterHiPSList({})
|
||||
});
|
||||
|
||||
|
||||
|
||||
const _parseHiPS = (e) => {
|
||||
const value = e.target.value;
|
||||
|
||||
@@ -131,6 +141,7 @@ export class HiPSBrowserBox extends Box {
|
||||
|
||||
let filterEnabler = Input.checkbox({
|
||||
name: "filter-enabler",
|
||||
tooltip: { content: "enable/disable" },
|
||||
checked: false,
|
||||
click(e) {
|
||||
let on = e.target.checked;
|
||||
@@ -271,6 +282,8 @@ export class HiPSBrowserBox extends Box {
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
filterEnabler.action({target: {checked: true}});
|
||||
}
|
||||
|
||||
_addHiPS(id, name) {
|
||||
@@ -429,7 +442,7 @@ export class HiPSBrowserBox extends Box {
|
||||
|
||||
_show(options) {
|
||||
// Regenerate a new layer name
|
||||
this.layer = Utils.uuidv4()
|
||||
this.layer = (options && options.layer) || Utils.uuidv4();
|
||||
|
||||
if (this.filterBox)
|
||||
this.filterBox.signalBrowserStatus(false)
|
||||
|
||||
@@ -53,7 +53,7 @@ export class HiPSFilterBox extends Box {
|
||||
url: freqIconUrl,
|
||||
},
|
||||
tooltip: {content: 'Observation bandwidth', position: {direction: 'bottom'}},
|
||||
toggled: true,
|
||||
toggled: false,
|
||||
actionOn: () => {
|
||||
self._triggerFilteringCallback();
|
||||
},
|
||||
|
||||
@@ -219,11 +219,6 @@ import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
value: 0.0,
|
||||
change: (e) => {
|
||||
let minCut = +e.target.value
|
||||
let imgFormat = self.options.layer.imgFormat;
|
||||
if (imgFormat !== "fits") {
|
||||
minCut /= 255.0;
|
||||
}
|
||||
|
||||
self.options.layer.setCuts(minCut, self.options.layer.getColorCfg().getCuts()[1])
|
||||
}
|
||||
},
|
||||
@@ -238,12 +233,6 @@ import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
value: 1.0,
|
||||
change: (e) => {
|
||||
let maxCut = +e.target.value
|
||||
|
||||
let imgFormat = self.options.layer.imgFormat;
|
||||
if (imgFormat !== "fits") {
|
||||
maxCut /= 255.0;
|
||||
}
|
||||
|
||||
self.options.layer.setCuts(self.options.layer.getColorCfg().getCuts()[0], maxCut)
|
||||
}
|
||||
}]
|
||||
@@ -302,10 +291,6 @@ import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
let reversed = colorCfg.getReversed();
|
||||
|
||||
let [minCut, maxCut] = colorCfg.getCuts();
|
||||
if (layer.imgFormat !== "fits") {
|
||||
minCut = Math.round(minCut * 255);
|
||||
maxCut = Math.round(maxCut * 255);
|
||||
}
|
||||
this.pixelSettingsContent.set('mincut', +minCut.toFixed(4))
|
||||
this.pixelSettingsContent.set('maxcut', +maxCut.toFixed(4))
|
||||
this.pixelSettingsContent.set('stretch', stretch)
|
||||
@@ -331,7 +316,7 @@ import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
update(options) {
|
||||
if (options.layer) {
|
||||
let self = this;
|
||||
if (options.layer.isSpectralCube()) {
|
||||
if (options.layer.isSpectralCube && options.layer.isSpectralCube()) {
|
||||
let spectraDisplayer = self.aladin.view.spectraDisplayer;
|
||||
|
||||
self.spectraBtn = new TogglerActionButton({
|
||||
|
||||
@@ -44,7 +44,6 @@ import settingsIconUrl from "../../../../assets/icons/settings.svg";
|
||||
import searchIconImg from "../../../../assets/icons/search.svg";
|
||||
import downloadIconUrl from '../../../../assets/icons/download.svg';
|
||||
|
||||
|
||||
import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
import { Icon } from "../Widgets/Icon.js";
|
||||
import { Box } from "../Widgets/Box.js";
|
||||
@@ -75,7 +74,7 @@ export class OverlayStackBox extends Box {
|
||||
};*/
|
||||
static predefinedCats = {
|
||||
simbad: {
|
||||
url: "https://axel.u-strasbg.fr/HiPSCatService/SIMBAD",
|
||||
url: "https://axel.cds.unistra.fr/HiPSCatService/SIMBAD",
|
||||
options: {
|
||||
id: "simbad",
|
||||
name: "SIMBAD",
|
||||
@@ -98,7 +97,7 @@ export class OverlayStackBox extends Box {
|
||||
},
|
||||
},
|
||||
gaia: {
|
||||
url: "https://axel.u-strasbg.fr/HiPSCatService/I/355/gaiadr3",
|
||||
url: "https://axel.cds.unistra.fr/HiPSCatService/I/355/gaiadr3",
|
||||
options: {
|
||||
id: "gaia-dr3",
|
||||
name: "Gaia DR3",
|
||||
@@ -109,7 +108,7 @@ export class OverlayStackBox extends Box {
|
||||
},
|
||||
},
|
||||
twomass: {
|
||||
url: "https://axel.u-strasbg.fr/HiPSCatService/II/246/out",
|
||||
url: "https://axel.cds.unistra.fr/HiPSCatService/II/246/out",
|
||||
options: {
|
||||
id: "2mass",
|
||||
name: "2MASS",
|
||||
@@ -731,6 +730,8 @@ export class OverlayStackBox extends Box {
|
||||
// one must add the current HiPS too!
|
||||
favoritesCopy.sort();
|
||||
|
||||
favoritesCopy.push("More...")
|
||||
|
||||
hips.HiPSSelector.update({value: currentHiPS, options: favoritesCopy});
|
||||
}
|
||||
});
|
||||
@@ -745,14 +746,6 @@ export class OverlayStackBox extends Box {
|
||||
}
|
||||
}
|
||||
|
||||
/*if (this.hipsBrowser) {
|
||||
this.hipsBrowser._hide();
|
||||
}*/
|
||||
|
||||
/*if (this.catBox) {
|
||||
this.catBox._hide();
|
||||
}*/
|
||||
|
||||
if (this.addOverlayBtn) this.addOverlayBtn.hideMenu();
|
||||
|
||||
if (this.addHiPSBtn) this.addHiPSBtn.hideMenu();
|
||||
@@ -781,7 +774,6 @@ export class OverlayStackBox extends Box {
|
||||
})
|
||||
);
|
||||
layout = layout.concat(this._createSurveysList());
|
||||
|
||||
return Layout.vertical({ layout });
|
||||
}
|
||||
|
||||
@@ -930,6 +922,7 @@ export class OverlayStackBox extends Box {
|
||||
options.push(value)
|
||||
}
|
||||
|
||||
options.push("More...")
|
||||
|
||||
let HiPSSelector = Input.select({
|
||||
value,
|
||||
@@ -937,6 +930,14 @@ export class OverlayStackBox extends Box {
|
||||
title: layer.name,
|
||||
change: (e) => {
|
||||
let name = e.target.value;
|
||||
|
||||
if (name === "More...") {
|
||||
if (!self.hipsBrowser)
|
||||
self.hipsBrowser = new HiPSBrowserBox(self.aladin);
|
||||
|
||||
self.hipsBrowser._show({ layer: layer.layer, position: { anchor: "center center" } });
|
||||
return;
|
||||
}
|
||||
// search for the
|
||||
let overlayLayer;
|
||||
if (name in self.cachedHiPS) {
|
||||
|
||||
@@ -225,6 +225,9 @@ export class Location extends DOMElement {
|
||||
// lon and lat must be given in cooFrame
|
||||
const updateFromLonLatFunc = (lon, lat, cooFrame) => {
|
||||
var coo = new Coo(lon, lat, Location.prec);
|
||||
|
||||
cooFrame = CooFrameEnum.fromString(cooFrame);
|
||||
|
||||
if (cooFrame == CooFrameEnum.ICRS) {
|
||||
self.field.set(coo.format('s/'));
|
||||
}
|
||||
|
||||
@@ -47,6 +47,28 @@ export class DOMElement {
|
||||
this.options = options;
|
||||
this.name = options && options.name || Utils.uuidv4()
|
||||
this.isHidden = true;
|
||||
|
||||
/*this.el.addEventListener("mouseup", (e) => {
|
||||
var wasDragging = view.realDragging === true;
|
||||
|
||||
if (view.dragging) { // if we were dragging, reset to default cursor
|
||||
if(view.mode === View.PAN) {
|
||||
view.setCursor('default');
|
||||
}
|
||||
|
||||
view.dragging = false;
|
||||
if (wasDragging) {
|
||||
view.realDragging = false;
|
||||
|
||||
// call the positionChanged once more with a dragging = false
|
||||
view.throttledPositionChanged(false);
|
||||
}
|
||||
|
||||
if (view.spectraDisplayer) {
|
||||
view.spectraDisplayer.enableInteraction();
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
element() {
|
||||
|
||||
@@ -270,7 +270,7 @@ export let Ellipse = (function() {
|
||||
if (! baseColor) {
|
||||
baseColor = '#ff0000';
|
||||
}
|
||||
|
||||
|
||||
if (this.isSelected) {
|
||||
if(this.selectionColor) {
|
||||
ctx.strokeStyle = this.selectionColor;
|
||||
@@ -318,8 +318,6 @@ export let Ellipse = (function() {
|
||||
let [xb, yb] = getVertexOnEllipse(3 * Math.PI * 0.5)
|
||||
let [xc, yc] = getVertexOnEllipse(Math.PI)
|
||||
let [xd, yd] = getVertexOnEllipse(0)
|
||||
ctx.save();
|
||||
|
||||
ctx.lineWidth = Math.max(this.lineWidth * 0.5, 1.0);
|
||||
ctx.setLineDash([this.lineWidth, this.lineWidth]);
|
||||
|
||||
@@ -329,8 +327,6 @@ export let Ellipse = (function() {
|
||||
ctx.lineTo(xd, yd);
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,16 +61,9 @@ export let Polyline = (function() {
|
||||
return mag2;
|
||||
}
|
||||
|
||||
function _drawLine(l, ctx, noStroke) {
|
||||
noStroke = noStroke===true || false;
|
||||
|
||||
ctx.beginPath();
|
||||
function _drawLine(l, ctx) {
|
||||
ctx.moveTo(l.x1, l.y1);
|
||||
ctx.lineTo(l.x2, l.y2);
|
||||
|
||||
if (!noStroke) {
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +225,6 @@ export let Polyline = (function() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
noSmallCheck = noSmallCheck===true || false;
|
||||
noStroke = noStroke===true || false;
|
||||
|
||||
@@ -270,8 +262,6 @@ export let Polyline = (function() {
|
||||
let ymin = Number.POSITIVE_INFINITY
|
||||
let ymax = Number.NEGATIVE_INFINITY;
|
||||
|
||||
|
||||
|
||||
let behind = true;
|
||||
for (var k=0; k<len; k++) {
|
||||
var xyview = view.aladin.world2pix(this.raDecArray[k][0], this.raDecArray[k][1]);
|
||||
@@ -380,10 +370,12 @@ export let Polyline = (function() {
|
||||
let v0 = this.closed ? len - 1 : 0;
|
||||
let v1 = this.closed ? 0 : 1;
|
||||
|
||||
ctx.globalAlpha = this.opacity;
|
||||
ctx.lineWidth = this.lineWidth;
|
||||
ctx.beginPath();
|
||||
|
||||
for (var k = 0; k < nSegment; k++) {
|
||||
|
||||
drawLine(xyView[v0], xyView[v1]);
|
||||
|
||||
v0 = v1;
|
||||
@@ -408,17 +400,15 @@ export let Polyline = (function() {
|
||||
v1 = v1 + 1;
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.fillStyle = this.fillColor;
|
||||
ctx.globalAlpha = this.opacity;
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Polyline.prototype.isInStroke = function(ctx, view, x, y) {
|
||||
ctx.beginPath()
|
||||
ctx.lineWidth = this.lineWidth;
|
||||
|
||||
let pointXY = [];
|
||||
@@ -441,8 +431,8 @@ export let Polyline = (function() {
|
||||
|
||||
if (v1 && v2) {
|
||||
const line = {x1: v1.x, y1: v1.y, x2: v2.x, y2: v2.y}; // new segment
|
||||
_drawLine(line, ctx, true);
|
||||
|
||||
_drawLine(line, ctx);
|
||||
|
||||
if (ctx.isPointInStroke(x, y)) { // x, y is on line?
|
||||
return true;
|
||||
}
|
||||
@@ -455,7 +445,7 @@ export let Polyline = (function() {
|
||||
|
||||
if (v1 && v2) {
|
||||
const line = {x1: v1.x, y1: v1.y, x2: v2.x, y2: v2.y}; // new segment
|
||||
_drawLine(line, ctx, true);
|
||||
_drawLine(line, ctx);
|
||||
|
||||
if (ctx.isPointInStroke(x, y)) { // x,y is on line?
|
||||
return true;
|
||||
|
||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 133 KiB |
103
vite.config.ts
@@ -7,56 +7,61 @@ import wasm from "vite-plugin-wasm";
|
||||
import topLevelAwait from "vite-plugin-top-level-await";
|
||||
// For wasm generated by wasm-pack
|
||||
import wasmPack from 'vite-plugin-wasm-pack';
|
||||
// To include and minify glsl into the bundle
|
||||
import glsl from 'vite-plugin-glsl';
|
||||
// To include css into the bundle
|
||||
//import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
minify: 'esbuild',
|
||||
lib: {
|
||||
// Could also be a dictionary or array of multiple entry points
|
||||
entry: resolve(__dirname, 'src/js/A.js'),
|
||||
name: 'A',
|
||||
formats: ["umd", "es"],
|
||||
// the proper extensions will be added
|
||||
fileName: 'aladin',
|
||||
import { visualizer } from "rollup-plugin-visualizer";
|
||||
|
||||
export default defineConfig(({mode}) => {
|
||||
return {
|
||||
build: {
|
||||
minify: 'esbuild',
|
||||
lib: {
|
||||
// Could also be a dictionary or array of multiple entry points
|
||||
entry: resolve(__dirname, 'src/js/A.js'),
|
||||
name: 'A',
|
||||
formats: ["umd", "es"],
|
||||
// the proper extensions will be added
|
||||
fileName: 'aladin',
|
||||
},
|
||||
rollupOptions: {},
|
||||
//formats: ["es"],
|
||||
target: ["es2015", "chrome58", "edge18", "firefox57", "node12", "safari11"],
|
||||
//target: ["es2015"],
|
||||
// Relative to the root
|
||||
outDir: resolve(__dirname, 'dist'),
|
||||
},
|
||||
rollupOptions: {},
|
||||
//formats: ["es"],
|
||||
target: ["es2015", "chrome58", "edge18", "firefox57", "node12", "safari11"],
|
||||
//target: ["es2015"],
|
||||
// Relative to the root
|
||||
outDir: resolve(__dirname, 'dist'),
|
||||
},
|
||||
//publicDir: resolve(__dirname, 'src/img'),
|
||||
plugins: [
|
||||
wasm(),
|
||||
wasmPack(resolve(__dirname, 'src/core')),
|
||||
topLevelAwait(),
|
||||
glsl({
|
||||
compress: true,
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
{find: '@', replacement: path.resolve(__dirname, '/src')},
|
||||
{find: '#', replacement: path.resolve(__dirname, '/tests/unit')},
|
||||
{find: '$', replacement: path.resolve(__dirname, '/tests/e2e')}
|
||||
//publicDir: resolve(__dirname, 'src/img'),
|
||||
plugins: [
|
||||
wasm(),
|
||||
wasmPack(resolve(__dirname, 'src/core')),
|
||||
topLevelAwait(),
|
||||
mode === 'analyze' &&
|
||||
visualizer({
|
||||
filename: 'stats.html', // output file
|
||||
template: 'treemap', // "sunburst", "treemap", "network"
|
||||
gzipSize: true, // show gzip sizes
|
||||
brotliSize: true, // show brotli sizes
|
||||
open: true // open stats.html automatically
|
||||
}),
|
||||
],
|
||||
},
|
||||
//test: {
|
||||
// globals: true,
|
||||
// environment: 'happy-dom',
|
||||
// include: [
|
||||
// 'tests/unit/**/*.{test,spec}.{js,ts}'
|
||||
// ],
|
||||
// deps: {
|
||||
// inline: ['core/pkg'],
|
||||
// },
|
||||
//},
|
||||
server: {
|
||||
open: '/examples/index.html',
|
||||
},
|
||||
resolve: {
|
||||
alias: [
|
||||
{find: '@', replacement: path.resolve(__dirname, '/src')},
|
||||
{find: '#', replacement: path.resolve(__dirname, '/tests/unit')},
|
||||
{find: '$', replacement: path.resolve(__dirname, '/tests/e2e')}
|
||||
],
|
||||
},
|
||||
//test: {
|
||||
// globals: true,
|
||||
// environment: 'happy-dom',
|
||||
// include: [
|
||||
// 'tests/unit/**/*.{test,spec}.{js,ts}'
|
||||
// ],
|
||||
// deps: {
|
||||
// inline: ['core/pkg'],
|
||||
// },
|
||||
//},
|
||||
server: {
|
||||
open: '/examples/index.html',
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||