Compare commits

...

14 Commits

Author SHA1 Message Date
Matthieu Baumann
645bab7cd9 Subdivision tuning
Cells are all subdivided at the same level.
One subdivision is added if:
* the cell is on a pole
* the cell is at a frontier of a base cells (and in collignon zona)
2025-04-09 13:35:20 +02:00
bmatthieu3
62f9e61978 New option to make the north pole remain up to the view
* lockNorthUp new Aladin init option. False by default.
* setRotation is still allowed if lockNorthUp=true but when panning, the
view resets its orientation so that the north pole is up
2025-04-09 13:35:20 +02:00
bmatthieu3
addbd555c1 Performance
Do all CPU computations on Vec3 and not Vec4
2025-04-09 13:35:20 +02:00
bmatthieu3
db70a6b9cd Set zoomfactor when using smartphones
Refers back to PR #249
2025-04-09 13:35:20 +02:00
bmatthieu3
258781d078 update readme, make the release page link more visible 2025-04-09 13:35:20 +02:00
bmatthieu3
7418ed822d add getZoomFactor method in Aladin 2025-04-09 13:35:20 +02:00
bmatthieu3
ba728c23c7 Enhance zooming on mouse/trackpad
When zooming with a mouse or a trackpad a wheel event is triggered.
Originally the fov of the viewport was changed but it happened setting
the fov is projection dependant therefore leading to big zooming effect
for TAN projection for example.
Now there is a new way of zooming which is done by setting the screen
zoom factor instead of the fov. Zooming with this factor is projection
agnostic.
With that the pr adds:
* an interpolated zooming effect moving the viewport from a start screen
zoom factor to another by following a hermite cubic interpolation
function
* bugfix: originally, multiple wheel events done shortly in time resulted in a
zooming "congestion" bug leading to a zoom effect similar to only one
isolated wheel event. Now triggering several wheel event allow to zoom
more than only one isolated.
* a new listener `wheelTriggered` allowing the user to define its own zooming.
When wheelTriggered is set, the default zooming is not executed
2025-04-09 13:35:20 +02:00
bmatthieu3
89f760c1db Update changelog 2025-04-09 13:35:20 +02:00
Matthieu Baumann
c5d0875265 First commit for 3.7.0
* add MOC setable properties: fill, edge and perimeter
* change package.json to 3.7.0-beta
2025-04-09 13:35:18 +02:00
Matthieu Baumann
4a8d3bfa65 Fix selection of footprints not associated with catalog sources
Targets #274

* fix: handleSelect now call selectObjects with not only the list of catalog sources but also with the footprints
* fix: View.closestFootprints: if no lineWidth was given to a footprint then it could happen that this method set it to 1px, erasing its previous undefined value
* Circle and Ellipse now behaves like PolyLine and Vector, if no linewidth is given, the one from its GraphicOverlay is taken.
2025-04-09 13:34:38 +02:00
Matthieu Baumann
bde5a37b51 codemeta 3.6.5 2025-04-09 13:33:29 +02:00
Matthieu Baumann
fbdc7e2e76 3.6.5 2025-04-09 11:57:10 +02:00
Matthieu Baumann
312b9844d1 Fix allsky fits display
Bug introduced in #254. Allsky is also downloaded if the tile_size is <= 256
2025-04-09 11:47:53 +02:00
bmatthieu3
0e740454bd Fix #278
When creating a new default survey the DSS2 survey is chosen. We use
the one cached instead of creating a plain new one.
2025-04-08 18:09:09 +02:00
138 changed files with 1440 additions and 982 deletions

View File

@@ -1,38 +1,113 @@
# Changelogs
## unreleased
## Unreleased
* [fix] request a redraw after adding an array of footprints [PR #218]
### What's Changed
## 3.5.1-beta
* [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.6.3
#### What's Changed
* [maint] remove Shift shorcut for triggering rectangular source selection. Shortcuts will be implemented later. by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/269>
* [fix] decide to show the contextual menu only if user has not right click while moving more than 10px. by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/269>
* [fix] CSS selector took the whole div in smartphone usage. by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/269>
* [fix] smartphone 2 fingers zoom pinching around the 180deg meridian. by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/269>
* [fix] use copy2Clipboard utils functions from contextual menu. by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/269>
* [fix] improved ID/HiPS url detection (retry if a relative path to a local HiPS is given as it is considered as an ID). by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/269>
### 3.6.1
#### What's Changed
* [feat] AVM tags support found in jpeg headers by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/178>
* [feat] Merge remove overlay by name to Develop by [@Xen0Xys][Xen0Xys] in <https://github.com/cds-astro/aladin-lite/pull/182>
* [fix] Restore A.footprint function by [@szpetny][szpetny] in <https://github.com/cds-astro/aladin-lite/pull/183>
* [testing] Merge playwright tests to Develop by [@Xen0Xys][Xen0Xys] in <https://github.com/cds-astro/aladin-lite/pull/176>
* [fix] Version 3.5.1 by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/180>
* [fix] Also add style sheet in shadow dom context by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/194>
* [feat] Add selectionColor, onClick to catalog parameters handled by updateShape by [@simontorres][simontorres] in <https://github.com/cds-astro/aladin-lite/pull/198>
* [feat] HiPS cube support by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/204>
* [feat] PolySelect implementation and miscellaneous selection improvements by [@pmatsson][pmatsson] in <https://github.com/cds-astro/aladin-lite/pull/195>
* [fix] Request a redraw after adding an array of footprints by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/218>
* [fix] Circle opacity not working by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/222>
* [fix] Bug introduced in #218 by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/223>
* [fix] CSS style for canvas element is more selective by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/224>
* [maint] Add zenodo.json file by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/226>
* [maint] Remove old files using jquery by [@cquiroz][cquiroz] in <https://github.com/cds-astro/aladin-lite/pull/231>
* [fix] Display of HiPS with maxOrder = 0 by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/236>
* [fix] Combine requestedOptions and Aladin.DEFAULT_OPTIONS with spread operator by [@pcuste1][pcuste1] in <https://github.com/cds-astro/aladin-lite/pull/237>
* [fix] Add back cmap reverse checkbox by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/238>
* [fix] JPEG draw black screen when tiles are missing by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/246>
* [fix] Filled moc drawing reverse longitude by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/250>
* [doc] Deprecate longitudeReversed HiPS options property by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/251>
* [fix] Stop contextmenu event propagation only if context menu enabled by [@alexgoff][alexgoff] in <https://github.com/cds-astro/aladin-lite/pull/259>
* [ui] Minor fixes and enhancements by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/256>
* [fix] Handle NaNs by the GPU (fix for windows) by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/254>
* [fix] Grid labels formatting by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/261>
* [feat] Shape function given to a catalog by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/262>
* [fix] Tooltip pos out of fov by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/263>
* [fix] MOC settings after its creation by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/265>
* [fix] ICRS to FK5J2000 cooframe renaming by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/264>
* [fix] Revert #264 by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/268>
#### New Contributors
* [@cquiroz][cquiroz] made their first contribution in <https://github.com/cds-astro/aladin-lite/pull/231>
* [@pcuste1][pcuste1] made their first contribution in <https://github.com/cds-astro/aladin-lite/pull/237>
* [@alexgoff][alexgoff] made their first contribution in <https://github.com/cds-astro/aladin-lite/pull/259>
**Full Changelog**: <https://github.com/cds-astro/aladin-lite/compare/3.4.5...3.6.1>
### 3.6.1-beta
#### What's Changed
* [feat] Add selectionColor, onClick to catalog parameters handled by updateShape by [@simontorres][simontorres] in <https://github.com/cds-astro/aladin-lite/pull/198>
* [feat] HiPS cube support by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/204>
* [feat] PolySelect implementation and miscellaneous selection improvements by [@pmatsson][pmatsson] in <https://github.com/cds-astro/aladin-lite/pull/195>
* [fix] Request a redraw after adding an array of footprints by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/218>
* [fix] Circle opacity not working by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/222>
* [fix] Bug introduced in #218 by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/223>
* [fix] CSS style for canvas element is more selective by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/224>
* [maint] add zenodo.json file by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/226>
* [maint] Remove old files using jquery by [@cquiroz][cquiroz] in <https://github.com/cds-astro/aladin-lite/pull/231>
#### New Contributors
* [@cquiroz][cquiroz] made their first contribution in <https://github.com/cds-astro/aladin-lite/pull/231>
**Full Changelog**: <https://github.com/cds-astro/aladin-lite/compare/3.5.1-beta...3.6.1-beta>
### 3.5.1-beta
* [feat] Add support for name removing in `removeOverlay` method
* [test] Add support of playwright. Instructions in the readme for running the test matching snapshots [PR #176]
* [fix] Order of overlays in the stack now matches the addMOC/addCatalog/addOverlay calls ordering
* [doc] Expose the API of Coo class
* [fix] Insert aladin css inside the aladin lite so that it should be compliant with the use of shadow DOMs [cds-astro/ipyaladin#113], [marimo-team/marimo#2106]
* [feat] Add possibility of giving a local JS FileList to load a locally-stored HiPS without starting an HTTP server [cds-astro/aladin-lite#103]
* [feat] Add possibility of giving a local JS FileList to load a locally-stored HiPS without starting an HTTP server <https://github.com/cds-astro/aladin-lite/pull/103>
* [fix] removeOverlayByName
## 3.5.0-beta
### 3.5.0-beta
* [enhancement] add `options.colnames` to A.catalogFromVizieR to tell VizieR we want absolutely want to retrieve specific columns
* [feat] provide a new drawAxes option to A.ellipse. This is useful for plotting error ellipsis.
## 3.4.5-beta
### 3.4.5-beta
* [feat] add `layerChanged` event when a layer is added or removed
* [deprecate] of `select` event, use `objectsSelected` event instead
* [ui] add the ability to switch the tile format to download
## 3.4.3-beta
### 3.4.3-beta
* [bugfix] zoom control buttons
* [feat] save a MOC as a JSON file from the UI <https://github.com/cds-astro/aladin-lite/issues/154>
* [feat] save a source selection from the measurement table as a CSV file
* [feat] allow to display jpeg/jpg images with a wcs passed as a JS dictionary: <https://github.com/cds-astro/aladin-lite/issues/173>
## 3.4.2-beta
### 3.4.2-beta
* [impr] Improve smartphone support by setting media queries + a better logic for deploying the contextual menu sub options.
* [impr] Improve `WCS` view export with 3rd euler rotation encoding: <https://github.com/cds-astro/aladin-lite/issues/170>. Still some cases are to be handled like: crval on the equator or cylindrical with a galactic frame rotation.
@@ -40,21 +115,21 @@
* [feat] Add new method `Aladin#getViewImageBuffer` to get the current view as a PNG buffer
* [feat] New line rasterizer using GL instancing. This enhances the rendering speed of MOCs.
## 3.3.3
### 3.3.3
* [feat] UI: add HiPS basic filter that filters the `hipsList` given
* [feat] New `hipsList` option parameter when instancing a new Aladin object.
* [feat] Zoom smoothing using hermite cubic interpolation functions
* [feat] shape option of Catalog and ProgressiveCat accepts a function returning a Footprint. This allow user to
associate a footprint to a specific source
* [feat] Hover color support by @pmatsson and @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/145>
* [feat] Hover color support by [@pmatsson][pmatsson] and [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/145>
## 3.3.2
### 3.3.2
* [fixed] do not allow to query the properties several times for an imageHiPS
* [fixed] Detecting raytracing rendering mode. Adapt the rendering mode in function of the fov value and the projection used. Some projections do have more distortions with wide FoVs so it is better to use the raytracing rendering mode when fov >= smaller FoV threshold.
## 3.3.0
### 3.3.0
* [fixed] multiple calls to setImageSurvey with the same survey object led to strange behaviour.
* [perf] Display the first tile received instantly with no blending. Should enhance the slow reported in issue #88.
@@ -75,61 +150,61 @@
* [fixed] The parameters `gridColor` and `gridOpacity`, `gridOptions.showLabels` now work as expected
* New documentation API (W.I.P) here: <https://cds-astro.github.io/aladin-lite/>
* New release page here: <https://aladin.cds.unistra.fr/AladinLite/doc/release/>
* A major UI update by @bmatthieu3
* A major UI update by [@bmatthieu3][bmatthieu3]
1. Some API new classes A.box, A.button
2. A status bar where the user can enque messages for a specific amount of time (Aladin.addStatusBarMessage)
* Remove of JQuery and autocompletejs dependencies by @bmatthieu3
* Fix some performances issues, i.e. a bug when resizing the aladin lite view and which launched several parallel requestAnimationFrame by @bmatthieu3
* Remove of JQuery and autocompletejs dependencies by [@bmatthieu3][bmatthieu3]
* Fix some performances issues, i.e. a bug when resizing the aladin lite view and which launched several parallel requestAnimationFrame by [@bmatthieu3][bmatthieu3]
* Polygon and circular selection (see Aladin class API documentation for how to use it)
* ObsCore and Datalink votable parsing and interpretation. This work is still in progress and made in the frame of the SKA radio mission by @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/116>
* SODA service query window formular by @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/116>
* read only catalog option by @szpetny in <https://github.com/cds-astro/aladin-lite/pull/117>
* Small changed regarding drawing a footprint by @szpetny in <https://github.com/cds-astro/aladin-lite/pull/118>
* Object and footprint click/hover events expose mouse coordinates by @szpetny in <https://github.com/cds-astro/aladin-lite/pull/121>
* A proposal of a new feature - fill the polygon with a color by @szpetny in <https://github.com/cds-astro/aladin-lite/pull/122>
* update getViewWCS to adapt to projection by @ManonMarchand in <https://github.com/cds-astro/aladin-lite/pull/119>
* New SAMP support by @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/128>
* A possibility to create Coo and Footprint objects by @szpetny in <https://github.com/cds-astro/aladin-lite/pull/130>
* ObsCore and Datalink votable parsing and interpretation. This work is still in progress and made in the frame of the SKA radio mission by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/116>
* SODA service query window formular by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/116>
* read only catalog option by [@szpetny][szpetny] in <https://github.com/cds-astro/aladin-lite/pull/117>
* Small changed regarding drawing a footprint by [@szpetny][szpetny] in <https://github.com/cds-astro/aladin-lite/pull/118>
* Object and footprint click/hover events expose mouse coordinates by [@szpetny][szpetny] in <https://github.com/cds-astro/aladin-lite/pull/121>
* A proposal of a new feature - fill the polygon with a color by [@szpetny][szpetny] in <https://github.com/cds-astro/aladin-lite/pull/122>
* update getViewWCS to adapt to projection by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/119>
* New SAMP support by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/128>
* A possibility to create Coo and Footprint objects by [@szpetny][szpetny] in <https://github.com/cds-astro/aladin-lite/pull/130>
* new method aladin.getFrame() that returns the name of the current coordinate system
* `getViewWCS` now adapts to the `cooFrame` and the `projection`
* `getFov` is no longer capped at 180°
* bugfix `setProjection` now also updates for 'PAR' and 'SFL' projections
## 3.2.0
### 3.2.0
* MOC rendering perf enhanced. Possibility to draw only the perimeter of a MOC object (perimeter set to True)
* Many fixes e.g. footprint rendering for all sky projections
* A line/shape webgl rasterizer thanks to the use of the `lyon`crate. MOCs and grid lines are rendered that way. Therefore, it is possible to change the grid lines thickness
* Use of vite for the project management and deployment
## 3.1.0
### 3.1.0
* Add message for safari users to enable WebGL2 feature and reload the page by @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/54>
* Starting fits support by @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/70>
* display fits images with the drag and drop by @bmatthieu3
* Add message for safari users to enable WebGL2 feature and reload the page by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/54>
* Starting fits support by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/70>
* display fits images with the drag and drop by [@bmatthieu3][bmatthieu3]
![Kapture 2023-03-23 at 14 34 28](https://user-images.githubusercontent.com/2772384/227264124-8e05a3d8-1565-497f-a118-39fab3c6ed83.gif)
* support `webp` tile format by @bmatthieu3 and @tboch
* planetary name resolver by @tboch
* small ui changes and bug fixes by @bmatthieu3
* add codemeta and its validatior action by @ManonMarchand in <https://github.com/cds-astro/aladin-lite/pull/66>
* support `webp` tile format by [@bmatthieu3][bmatthieu3] and [@tboch][tboch]
* planetary name resolver by [@tboch][tboch]
* small ui changes and bug fixes by [@bmatthieu3][bmatthieu3]
* add codemeta and its validatior action by [@ManonMarchand][ManonMarchand] in <https://github.com/cds-astro/aladin-lite/pull/66>
## 3.0.0
### 3.0.0
Official release of Aladin Lite v3, [as announced in CDS news](https://cds.unistra.fr/news.php?fn_mode=fullnews&fn_incl=0&fn_id=958).
* Fix missing tiles issue by @tboch in <https://github.com/cds-astro/aladin-lite/pull/18>
* Hips catalogue filtering by @tboch in <https://github.com/cds-astro/aladin-lite/pull/28>
* Make footprint selection easier by @tboch in <https://github.com/cds-astro/aladin-lite/pull/19>
* Bug fix: enable different colors for multiple polylines in same layer by @tboch in <https://github.com/cds-astro/aladin-lite/pull/30>
* Method remove to delete individual source from a catalogue layer by @tboch in <https://github.com/cds-astro/aladin-lite/pull/37>
* Stop animation by @tboch in <https://github.com/cds-astro/aladin-lite/pull/40>
* Add message for safari users to enable WebGL2 feature and reload the page by @bmatthieu3 in <https://github.com/cds-astro/aladin-lite/pull/54>
* Fix missing tiles issue by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/18>
* Hips catalogue filtering by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/28>
* Make footprint selection easier by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/19>
* Bug fix: enable different colors for multiple polylines in same layer by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/30>
* Method remove to delete individual source from a catalogue layer by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/37>
* Stop animation by [@tboch][tboch] in <https://github.com/cds-astro/aladin-lite/pull/40>
* Add message for safari users to enable WebGL2 feature and reload the page by [@bmatthieu3][bmatthieu3] in <https://github.com/cds-astro/aladin-lite/pull/54>
## 2.x.x
## Version: 2.x.x
### 2020-08
* polyline improvements (by @imbasimba)
* polyline improvements (by [@imbasimba][imbasimba])
### 2020-07
@@ -394,3 +469,33 @@ New in the API:
* ajout catalogue progressif
* ajout on select, objectClicked, objectHovered
## Contributors
Aladin Lite is made possible thanks to those people:
* [@alexgoff][alexgoff]
* [@bmatthieu3][bmatthieu3]
* [@cquiroz][cquiroz]
* [@imbasimba][imbasimba]
* [@ManonMarchand][ManonMarchand]
* [@pcuste1][pcuste1]
* [@pmatsson][pmatsson]
* [@simontorres][simontorres]
* [@szpetny][szpetny]
* [@tboch][tboch]
* [@Xen0Xys][Xen0Xys]
[alexgoff]: https://github.com/alexgoff
[bmatthieu3]: https://github.com/bmatthieu3
[cquiroz]: https://github.com/cquiroz
[imbasimba]: https://github.com/imbasimba
[ManonMarchand]: https://github.com/ManonMarchand
[pcuste1]: https://github.com/pcuste1
[pmatsson]: https://github.com/pmatsson
[simontorres]: https://github.com/simontorres
[szpetny]: https://github.com/szpetny
[tboch]: https://github.com/tboch
[Xen0Xys]: https://github.com/Xen0Xys

View File

@@ -13,7 +13,7 @@ A new [API technical documentation](https://cds-astro.github.io/aladin-lite/) is
[![Run tests](https://github.com/cds-astro/aladin-lite/actions/workflows/test.yml/badge.svg)](https://github.com/cds-astro/aladin-lite/actions/workflows/test.yml)
[![API Documentation](https://img.shields.io/badge/API-documentation-blue.svg)](https://cds-astro.github.io/aladin-lite)
[![Releases page](https://img.shields.io/badge/Releases-forge-yellow.svg)](https://aladin.cds.unistra.fr/AladinLite/doc/release/)
[![Release page](https://img.shields.io/badge/Release-download-yellow.svg)](https://aladin.cds.unistra.fr/AladinLite/doc/release/)
Aladin Lite is available [at this link](https://aladin.u-strasbg.fr/AladinLite).

View File

@@ -8,8 +8,8 @@
"dateModified": "2023-01-31",
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
"name": "Aladin Lite",
"version": "3.6.4",
"softwareVersion": "3.6.4",
"version": "3.6.5",
"softwareVersion": "3.6.5",
"description": "An astronomical HiPS visualizer in the browser.",
"identifier": "10.5281/zenodo.7638833",
"applicationCategory": "Astronomy, Visualization",

View File

@@ -4,7 +4,7 @@
</head>
<body>
<div id="aladin-lite-div" style="width: 1024px; height: 256px;"></div>
<div id="aladin-lite-div" style="width: 1024px; height: 768px;"></div>
<script type="module">
import A from '../src/js/A.js';
@@ -13,12 +13,14 @@
var aladin = A.aladin(
'#aladin-lite-div',
{
survey: 'https://alasky.cds.unistra.fr/Pan-STARRS/DR1/color-z-zg-g/', // set initial image survey
survey: 'data/hips/wcs', // set initial image survey
projection: 'SIN', // set a projection
fov: 114.19, // initial field of view in degrees
target: '19 24 51.556 +45 16 44.36', // initial target
cooFrame: 'equatorial', // set galactic frame
showCooGrid: true, // set the grid
fov: 80.0, // initial field of view in degrees
target: '96.5279427 -88.0037230', // initial target
cooFrame: 'galactic', // set galactic frame
showCooGrid: true, // set the grid,
fullScreen: true,
showSettingsControl: true,
}
);
});

View File

@@ -11,7 +11,7 @@
let aladin;
A.init.then(() => {
// Start up Aladin Lite
aladin = A.aladin('#aladin-lite-div', {survey: "CDS/P/DSS2/color", target: 'M 1', fov: 0.2, showContextMenu: true, fullScreen: true});
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]});
aladin.addOverlay(overlay);
overlay.addFootprints([

View File

@@ -7,7 +7,7 @@
<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/DSS2/color", target: "280 +0", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
let aladin = A.aladin('#aladin-lite-div', {fov: 30, target: "280 +0", projection: "AIT", showShareControl:true, showSettingsControl: true, showContextMenu:true});
aladin.setOverlayImageLayer(A.image(
"https://www.virtualastronomy.org/images/sig05-013.jpg",

View File

@@ -30,17 +30,9 @@
fullScreen: true,
samp: true,
realFullscreen: true,
lockNorthUp: true,
}
);
/*let id;
aladin.on("zoomChanged", () => {
if (id)
clearTimeout(id);
id = setTimeout(() => {
console.log("wheel stopped, new cone search here")
}, 500);
})*/
});
</script>
</body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -0,0 +1,33 @@
creator_did = ivo://UNK.AUTH/P/474-2244-wcs
obs_title = 474-2244-wcs.fits
hips_builder = Aladin/HipsGen v12.135
hips_version = 1.4
hips_frame = galactic
hips_order = 10
hips_order_min = 0
hips_tile_width = 512
hips_status = public master clonableOnce
hips_tile_format = png
hips_pixel_bitpix = -32
hips_pixel_cut = -670.2 64044
hips_data_range = -38085 98627
hips_initial_ra = 11.66767
hips_initial_dec = -24.86479
hips_initial_fov = 5.90651
hips_pixel_scale = 1.118E-4
s_pixel_scale = 1.222E-4
dataproduct_type = image
hipsgen_date = 2024-11-13T17:07Z
hipsgen_params = in=NAROO/474-2244-wcs.fits out=/var/www/tmp/HiPS/474-2244-wcs id=474-2244-wcs maxThread=20
data_pixel_bitpix = -32
hips_sampling = bilinear
hips_overlay = overlayMean mergeOverwrite treeMean
hips_release_date = 2024-11-13T18:33Z
hips_data_minmax = -21385 73221
moc_sky_fraction = 0.001074
hipsgen_date_1 = 2024-11-13T18:25Z
hipsgen_params_1 = in=NAROO/474-2244-wcs.fits out=/var/www/tmp/HiPS/474-2244-wcs id=474-2244-wcs maxThread=20
hips_creation_date = 2024-11-13T18:25Z
hips_estsize = 24116525
hips_nb_tiles = 36636
hips_check_code = png:735272809

View File

@@ -2,7 +2,7 @@
"homepage": "https://aladin.u-strasbg.fr/",
"name": "aladin-lite",
"type": "module",
"version": "3.6.4",
"version": "3.7.0-beta",
"description": "An astronomical HiPS visualizer in the browser",
"author": "Thomas Boch and Matthieu Baumann",
"license": "GPL-3",

View File

@@ -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.6.4"
version = "3.7.0"
authors = [ "baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr",]
edition = "2018"
@@ -88,4 +88,4 @@ codegen-units = 16
rpath = false
[package.metadata.wasm-pack.profile.release]
wasm-opt = true
wasm-opt = false

View File

@@ -1,6 +1,6 @@
[package]
name = "al-api"
version = "3.6.4"
version = "3.6.5"
authors = ["baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr"]
edition = "2018"

View File

@@ -1,45 +1,37 @@
use cgmath::Matrix4;
use cgmath::Matrix3;
const GAL2ICRS: &'static Matrix4<f64> = &Matrix4::new(
const GAL2ICRS: &'static Matrix3<f64> = &Matrix3::new(
-0.44482972122205372312012370920248,
0.74698218398450941835110635824212,
0.49410943719710765017955928850141,
0.0,
-0.19807633727507056817237662907031,
0.45598381369115237931077906137440,
-0.86766613755716255824577781583414,
0.0,
-0.87343705195577915249273984034980,
-0.48383507361641838378786914298189,
-0.05487565771261968232908806948676,
0.0,
0.0,
0.0,
0.0,
1.0,
);
const ICRS2GAL: &'static Matrix4<f64> = &Matrix4::new(
const ICRS2GAL: &'static Matrix3<f64> = &Matrix3::new(
-0.44482972122205372312012370920248,
-0.19807633727507056817237662907031,
-0.87343705195577915249273984034980,
0.0,
0.74698218398450941835110635824212,
0.45598381369115237931077906137440,
-0.48383507361641838378786914298189,
0.0,
0.49410943719710765017955928850141,
-0.86766613755716255824577781583414,
-0.05487565771261968232908806948676,
0.0,
0.0,
0.0,
0.0,
1.0,
);
const ID: &'static Matrix4<f64> = &Matrix4::new(
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
const ID: &'static Matrix3<f64> = &Matrix3::new(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
);
@@ -56,7 +48,7 @@ pub const NUM_COOSYSTEM: usize = 2;
impl CooSystem {
#[inline]
pub fn to(&self, coo_system: Self) -> &Matrix4<f64> {
pub fn to(&self, coo_system: Self) -> &Matrix3<f64> {
match (self, coo_system) {
(CooSystem::GAL, CooSystem::ICRS) => GAL2ICRS,
(CooSystem::ICRS, CooSystem::GAL) => ICRS2GAL,

View File

@@ -1,6 +1,6 @@
[package]
name = "al-core"
version = "3.6.4"
version = "3.6.5"
authors = ["baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr"]
edition = "2018"

View File

@@ -218,19 +218,19 @@ impl UniformType for Matrix2<f32> {
}
}
use cgmath::Matrix4;
impl UniformType for Matrix4<f32> {
use cgmath::Matrix3;
impl UniformType for Matrix3<f32> {
fn uniform(gl: &WebGlContext, location: Option<&WebGlUniformLocation>, value: &Self) {
gl.uniform_matrix4fv_with_f32_array(location, false, value.as_ref() as &[f32; 16]);
gl.uniform_matrix3fv_with_f32_array(location, false, value.as_ref() as &[f32; 9]);
}
}
use crate::Abort;
impl UniformType for Matrix4<f64> {
impl UniformType for Matrix3<f64> {
fn uniform(gl: &WebGlContext, location: Option<&WebGlUniformLocation>, value: &Self) {
// Cast the matrix
let mat_f32 = value.cast::<f32>().unwrap_abort();
gl.uniform_matrix4fv_with_f32_array(location, false, mat_f32.as_ref() as &[f32; 16]);
gl.uniform_matrix3fv_with_f32_array(location, false, mat_f32.as_ref() as &[f32; 9]);
}
}
use super::texture::Texture2D;

View File

@@ -35,7 +35,6 @@ use al_api::{
grid::GridCfg,
hips::{HiPSCfg, ImageMetadata},
};
use cgmath::Vector4;
use fitsrs::{fits::AsyncFits, hdu::extension::AsyncXtensionHDU};
use web_sys::{HtmlElement, WebGl2RenderingContext};
@@ -75,6 +74,7 @@ pub struct App {
// Task executor
//exec: Rc<RefCell<TaskExecutor>>,
inertia: Option<Inertia>,
north_up: bool,
disable_inertia: Rc<RefCell<bool>>,
dist_dragging: f32,
time_start_dragging: Time,
@@ -172,7 +172,7 @@ impl App {
//let tasks_finished = false;
let request_redraw = false;
let rendering = true;
let prev_cam_position = camera.get_center().truncate();
let prev_cam_position = *camera.get_center();
//let prev_center = Vector3::new(0.0, 1.0, 0.0);
let out_of_fov = false;
let catalog_loaded = false;
@@ -244,7 +244,7 @@ impl App {
catalog_loaded,
tile_fetcher,
north_up: false,
colormaps,
projection,
@@ -421,17 +421,17 @@ impl App {
let v = cell.vertices();
let proj2screen = |(lon, lat): &(f64, f64)| -> Option<[f64; 2]> {
// 1. convert to xyzw
let xyzw = crate::math::lonlat::radec_to_xyzw(lon.to_angle(), lat.to_angle());
// 1. convert to xyz
let xyz = crate::math::lonlat::radec_to_xyz(lon.to_angle(), lat.to_angle());
// 2. get it back to the camera frame system
let xyzw = crate::coosys::apply_coo_system(
let xyz = crate::coosys::apply_coo_system(
CooSystem::ICRS,
self.camera.get_coo_system(),
&xyzw,
&xyz,
);
// 3. project on screen
if let Some(p) = self.projection.model_to_clip_space(&xyzw, &self.camera) {
if let Some(p) = self.projection.model_to_clip_space(&xyz, &self.camera) {
Some([p.x, p.y])
} else {
None
@@ -1353,11 +1353,12 @@ impl App {
pub(crate) fn resize(&mut self, width: f32, height: f32) {
self.camera.set_screen_size(width, height, &self.projection);
self.camera
.set_aperture(self.camera.get_aperture(), &self.projection);
.set_zoom_factor(self.camera.get_zoom_factor(), &self.projection);
// resize the view fbo
let screen_size = self.camera.get_screen_size();
self._fbo_view
.resize(screen_size.x as usize, screen_size.y as usize);
//let screen_size = self.camera.get_screen_size();
//self._fbo_view
// .resize(screen_size.x as usize, screen_size.y as usize);
// resize the ui fbo
//self.fbo_ui.resize(w as usize, h as usize);
@@ -1443,9 +1444,9 @@ impl App {
}
pub(crate) fn view_to_icrs_coosys(&self, lonlat: &LonLatT<f64>) -> LonLatT<f64> {
let celestial_pos: Vector4<_> = lonlat.vector();
let celestial_pos = lonlat.vector();
let view_system = self.camera.get_coo_system();
let (ra, dec) = math::lonlat::xyzw_to_radec(&coosys::apply_coo_system(
let (ra, dec) = math::lonlat::xyz_to_radec(&coosys::apply_coo_system(
view_system,
CooSystem::ICRS,
&celestial_pos,
@@ -1456,7 +1457,7 @@ impl App {
/// lonlat must be given in icrs frame
pub(crate) fn set_center(&mut self, lonlat: &LonLatT<f64>) {
self.prev_cam_position = self.camera.get_center().truncate();
self.prev_cam_position = *self.camera.get_center();
self.camera.set_center(lonlat, &self.projection);
self.request_for_new_tiles = true;
@@ -1520,11 +1521,11 @@ impl App {
return;
}
let now = Time::now();
let dragging_duration = (now - self.time_start_dragging).as_secs();
let dragging_vel = self.dist_dragging / dragging_duration;
let _dist_dragging = self.dist_dragging;
// 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
@@ -1537,31 +1538,31 @@ impl App {
// Start inertia here
// Angular distance between the previous and current
// center position
let center = self.camera.get_center().truncate();
let axis = self.prev_cam_position.cross(center).normalize();
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;
self.inertia = Some(Inertia::new(ampl.to_radians(), axis))
self.inertia = Some(Inertia::new(ampl.to_radians(), axis, self.north_up))
}
pub(crate) fn set_view_center_pos_angle(&mut self, theta: ArcDeg<f64>) {
pub(crate) fn set_position_angle(&mut self, theta: ArcDeg<f64>) {
self.camera
.set_center_pos_angle(theta.into(), &self.projection);
.set_position_angle(theta.into(), &self.projection);
// New tiles can be needed and some tiles can be removed
self.request_for_new_tiles = true;
self.request_redraw = true;
}
pub(crate) fn get_north_shift_angle(&self) -> Angle<f64> {
self.camera.get_center_pos_angle()
pub(crate) fn get_position_angle(&self) -> Angle<f64> {
self.camera.get_position_angle()
}
pub(crate) fn set_fov(&mut self, fov: Angle<f64>) {
pub(crate) fn set_fov(&mut self, fov: f64) {
// For the moment, no animation is triggered.
// The fov is directly set
self.camera.set_aperture(fov, &self.projection);
@@ -1569,17 +1570,20 @@ impl App {
self.request_redraw = true;
}
pub(crate) fn set_fov_range(&mut self, min_fov: Option<f64>, max_fov: Option<f64>) {
self.camera.set_fov_range(
min_fov.map(|v| v.to_radians()),
max_fov.map(|v| v.to_radians()),
&self.projection,
);
self.request_for_new_tiles = true;
self.request_redraw = true;
}
pub(crate) fn set_inertia(&mut self, inertia: bool) {
*self.disable_inertia.borrow_mut() = !inertia;
}
/*pub(crate) fn project_line(&self, lon1: f64, lat1: f64, lon2: f64, lat2: f64) -> Vec<Vector2<f64>> {
let v1: Vector3<f64> = LonLatT::new(ArcDeg(lon1).into(), ArcDeg(lat1).into()).vector();
let v2: Vector3<f64> = LonLatT::new(ArcDeg(lon2).into(), ArcDeg(lat2).into()).vector();
line::project_along_great_circles(&v1, &v2, &self.camera, self.projection)
}*/
pub(crate) fn go_from_to(&mut self, s1x: f64, s1y: f64, s2x: f64, s2y: f64) {
// Select the HiPS layer rendered lastly
if let (Some(w1), Some(w2)) = (
@@ -1588,22 +1592,65 @@ impl App {
self.projection
.screen_to_model_space(&Vector2::new(s2x, s2y), &self.camera),
) {
let prev_pos = w1.truncate();
//let cur_pos = w1.truncate();
let cur_pos = w2.truncate();
//let next_pos = w2.truncate();
let prev_pos = w1;
let cur_pos = w2;
if prev_pos != cur_pos {
/* 1. Rotate by computing the angle between the last and current position */
let prev_cam_position = self.camera.get_center().clone();
// Apply the rotation to the camera to
// go from the current pos to the next position
let axis = prev_pos.cross(cur_pos).normalize();
if self.north_up {
let lonlat1 = prev_pos.lonlat();
let lonlat2 = cur_pos.lonlat();
let d = math::vector::angle3(&prev_pos, &cur_pos);
let dlon = lonlat2.lon() - lonlat1.lon();
let dlat = lonlat2.lat() - lonlat1.lat();
self.camera.apply_lonlat_rotation(dlon, dlat, &self.projection);
self.prev_cam_position = self.camera.get_center().truncate();
self.camera.apply_rotation(&(-axis), d, &self.projection);
// Detect if a pole has been crossed
let north_pole = Vector3::new(0.0, 1.0, 0.0);
let south_pole = Vector3::new(0.0, -1.0, 0.0);
let cross_north_pole = crate::math::lonlat::is_in(&prev_cam_position, &self.camera.get_center(), &north_pole);
let cross_south_pole = crate::math::lonlat::is_in(&prev_cam_position, &self.camera.get_center(), &south_pole);
let cross_pole = cross_north_pole | cross_south_pole;
// Detect if a pole has been crossed
let center = if cross_pole {
&prev_cam_position
} else {
self.camera.get_center()
};
let fov = self.camera.get_aperture();
let pole = if center.y >= 0.0 {
north_pole
} else {
south_pole
};
let c2p = crate::math::vector::angle3(center, &pole).to_radians();
let near_pole = c2p.abs() < 5e-3 * fov;
if near_pole || cross_pole {
// too near to the pole
let axis = center.cross(pole).normalize();
use crate::math::rotation::Rotation;
let new_center = Rotation::from_axis_angle(&axis, (-5e-3 * fov).to_angle()).rotate(&pole);
self.camera.set_center_xyz(&new_center, &self.projection);
self.camera.set_position_angle(0.0.to_angle(), &self.projection);
}
} 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();
self.camera.apply_axis_rotation(&(-axis), d, &self.projection);
}
self.prev_cam_position = prev_cam_position;
self.request_for_new_tiles = true;
}
} else {
@@ -1611,6 +1658,10 @@ impl App {
}
}
pub(crate) fn lock_north_up(&mut self) {
self.north_up = true;
}
pub(crate) fn add_cmap(&mut self, label: String, cmap: Colormap) -> Result<(), JsValue> {
self.colormaps.add_cmap(label, cmap)
}
@@ -1624,13 +1675,19 @@ impl App {
self.camera.get_texture_depth() as i32
}
pub(crate) fn get_clip_zoom_factor(&self) -> f64 {
self.camera.get_clip_zoom_factor()
pub(crate) fn get_zoom_factor(&self) -> f64 {
self.camera.get_zoom_factor()
}
pub(crate) fn set_zoom_factor(&mut self, zoom_factor: f64) {
self.camera.set_zoom_factor(zoom_factor, &self.projection);
self.request_for_new_tiles = true;
self.request_redraw = true;
}
pub(crate) fn get_fov(&self) -> f64 {
let deg: ArcDeg<f64> = self.camera.get_aperture().into();
deg.0
self.camera.get_aperture().to_degrees()
}
pub(crate) fn get_colormaps(&self) -> &Colormaps {

View File

@@ -1,6 +1,6 @@
use cgmath::{Matrix4, Vector2};
use cgmath::{Matrix3, Vector2};
use crate::math::projection::coo_space::{XYZWModel, XYZWWorld, XYNDC};
use crate::math::projection::coo_space::{XYZModel, XYZWorld, XYNDC};
use crate::math::sph_geom::region::{Intersection, PoleContained, Region};
use crate::math::{projection::Projection, sph_geom::bbox::BoundingBox};
@@ -14,7 +14,7 @@ fn ndc_to_world(
ndc_to_clip: &Vector2<f64>,
clip_zoom_factor: f64,
projection: &ProjectionType,
) -> Option<Vec<XYZWWorld<f64>>> {
) -> Option<Vec<XYZWorld<f64>>> {
// Deproject the FOV from ndc to the world space
let mut world_coo = Vec::with_capacity(ndc_coo.len());
@@ -34,7 +34,7 @@ fn ndc_to_world(
Some(world_coo)
}
fn world_to_model(world_coo: &[XYZWWorld<f64>], w2m: &Matrix4<f64>) -> Vec<XYZWModel<f64>> {
fn world_to_model(world_coo: &[XYZWorld<f64>], w2m: &Matrix3<f64>) -> Vec<XYZModel<f64>> {
let mut model_coo = Vec::with_capacity(world_coo.len());
for w in world_coo.iter() {
@@ -61,8 +61,8 @@ const NUM_VERTICES: usize = 4 + 2 * NUM_VERTICES_WIDTH + 2 * NUM_VERTICES_HEIGHT
pub struct FieldOfView {
// Vertices
ndc_vertices: Vec<XYNDC<f64>>,
world_vertices: Option<Vec<XYZWWorld<f64>>>,
model_vertices: Option<Vec<XYZWModel<f64>>>,
world_vertices: Option<Vec<XYZWorld<f64>>>,
model_vertices: Option<Vec<XYZModel<f64>>>,
reg: Region,
}
@@ -73,7 +73,7 @@ impl FieldOfView {
ndc_to_clip: &Vector2<f64>,
clip_zoom_factor: f64,
// rotation
rotation_mat: &Matrix4<f64>,
rotation_mat: &Matrix3<f64>,
// projection
projection: &ProjectionType,
) -> Self {
@@ -123,7 +123,7 @@ impl FieldOfView {
&mut self,
ndc_to_clip: &Vector2<f64>,
clip_zoom_factor: f64,
rotate_mat: &Matrix4<f64>,
rotate_mat: &Matrix3<f64>,
projection: &ProjectionType,
) {
self.world_vertices = ndc_to_world(
@@ -135,7 +135,7 @@ impl FieldOfView {
self.set_rotation(rotate_mat);
}
pub fn set_rotation(&mut self, rotate_mat: &Matrix4<f64>) {
pub fn set_rotation(&mut self, rotate_mat: &Matrix3<f64>) {
if let Some(world_vertices) = &self.world_vertices {
self.model_vertices = Some(world_to_model(world_vertices, rotate_mat));
} else {
@@ -186,7 +186,7 @@ impl FieldOfView {
}
}
pub fn get_vertices(&self) -> Option<&Vec<XYZWModel<f64>>> {
pub fn get_vertices(&self) -> Option<&Vec<XYZModel<f64>>> {
self.model_vertices.as_ref()
}

View File

@@ -1,6 +1,6 @@
pub mod viewport;
use crate::math::lonlat::LonLat;
use crate::math::projection::coo_space::XYZWModel;
use crate::math::projection::coo_space::XYZModel;
pub use viewport::CameraViewPort;
pub mod fov;
@@ -14,7 +14,7 @@ use crate::ProjectionType;
pub fn build_fov_coverage(
depth: u8,
fov: &FieldOfView,
camera_center: &XYZWModel<f64>,
camera_center: &XYZModel<f64>,
camera_frame: CooSystem,
frame: CooSystem,
proj: &ProjectionType,
@@ -40,7 +40,7 @@ pub fn build_fov_coverage(
// See https://github.com/cds-astro/cds-moc-rust/issues/3
let hpx_idxs_iter = vertices_iter.map(|v| {
let (lon, lat) = crate::math::lonlat::xyzw_to_radec(&v);
let (lon, lat) = crate::math::lonlat::xyz_to_radec(&v);
::healpix::nested::hash(depth, lon.to_radians(), lat.to_radians())
});
@@ -55,10 +55,10 @@ pub fn build_fov_coverage(
moc
}
} else {
let center_xyzw = crate::coosys::apply_coo_system(camera_frame, frame, camera_center);
let center_xyz = crate::coosys::apply_coo_system(camera_frame, frame, camera_center);
let biggest_fov_rad = proj.aperture_start().to_radians();
let lonlat = center_xyzw.lonlat();
let lonlat = center_xyz.lonlat();
HEALPixCoverage::from_cone(&lonlat, biggest_fov_rad * 0.5, depth)
}
}

View File

@@ -1,4 +1,4 @@
use crate::camera::XYZWModel;
use crate::camera::XYZModel;
use crate::healpix::cell::HEALPixCell;
use crate::math::projection::*;
@@ -30,7 +30,7 @@ impl ViewHpxCells {
&mut self,
camera_depth: u8,
fov: &FieldOfView,
center: &XYZWModel<f64>,
center: &XYZModel<f64>,
camera_frame: CooSystem,
proj: &ProjectionType,
// survey frame
@@ -48,7 +48,7 @@ impl ViewHpxCells {
&mut self,
camera_depth: u8,
fov: &FieldOfView,
center: &XYZWModel<f64>,
center: &XYZModel<f64>,
camera_frame: CooSystem,
proj: &ProjectionType,
// survey frame
@@ -68,7 +68,7 @@ impl ViewHpxCells {
&mut self,
camera_depth: u8,
fov: &FieldOfView,
center: &XYZWModel<f64>,
center: &XYZModel<f64>,
camera_frame: CooSystem,
proj: &ProjectionType,
) {
@@ -149,7 +149,7 @@ impl HpxCells {
&mut self,
camera_depth: u8,
fov: &FieldOfView,
center: &XYZWModel<f64>,
center: &XYZModel<f64>,
camera_frame: CooSystem,
proj: &ProjectionType,
) {

View File

@@ -8,26 +8,32 @@ pub enum UserAction {
use web_sys::WebGl2RenderingContext;
// Longitude reversed identity matrix
const ID_R: &Matrix4<f64> = &Matrix4::new(
-1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
const ID_R: &Matrix3<f64> = &Matrix3::new(
-1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
);
use cgmath::{Vector3, InnerSpace};
use super::{fov::FieldOfView, view_hpx_cells::ViewHpxCells};
use crate::healpix::cell::HEALPixCell;
use crate::healpix::coverage::HEALPixCoverage;
use crate::math::angle::ToAngle;
use crate::math::{projection::coo_space::XYZWModel, projection::domain::sdf::ProjDef};
use crate::math::{projection::coo_space::XYZModel, projection::domain::sdf::ProjDef};
use cgmath::{Matrix3, Vector2};
const APERTURE_LOWER_LIMIT_RAD: f64 = (1.0_f64 / 36000.0).to_radians();
const ZOOM_FACTOR_UPPER_LIMIT: f64 = 2.0;
use cgmath::{Matrix4, Vector2};
pub struct CameraViewPort {
// The field of view angle
aperture: Angle<f64>,
aperture: f64,
// The rotation of the camera
center: Vector4<f64>,
center: Vector3<f64>,
w2m_rot: Rotation<f64>,
w2m: Matrix4<f64>,
m2w: Matrix4<f64>,
w2m: Matrix3<f64>,
m2w: Matrix3<f64>,
// The width over height ratio
aspect: f32,
// The width of the screen in pixels
@@ -44,7 +50,7 @@ pub struct CameraViewPort {
// Internal variable used for projection purposes
ndc_to_clip: Vector2<f64>,
clip_zoom_factor: f64,
zoom_factor: f64,
// The vertices in model space of the camera
// This is useful for computing views according
// to different image surveys
@@ -71,6 +77,11 @@ pub struct CameraViewPort {
gl: WebGlContext,
coo_sys: CooSystem,
reversed_longitude: bool,
// min field of view, by default 0.1 arcsec
pub(crate) min_fov: Option<f64>,
// an optional max field of view
pub(crate) max_fov: Option<f64>,
}
use al_api::coo_system::CooSystem;
use al_core::WebGlContext;
@@ -81,7 +92,7 @@ use crate::{
};
use crate::LonLatT;
use cgmath::{SquareMatrix, Vector4};
use cgmath::SquareMatrix;
use wasm_bindgen::JsCast;
const MAX_DPI_LIMIT: f32 = 2.0;
@@ -96,11 +107,11 @@ impl CameraViewPort {
) -> CameraViewPort {
let last_user_action = UserAction::Starting;
let aperture = projection.aperture_start();
let aperture = projection.aperture_start().to_radians();
let w2m = Matrix4::identity();
let w2m = Matrix3::identity();
let m2w = w2m;
let center = Vector4::new(0.0, 0.0, 0.0, 1.0);
let center = Vector3::new(0.0, 0.0, 0.0);
let moved = false;
let zoomed = false;
@@ -122,9 +133,9 @@ impl CameraViewPort {
let aspect = height / width;
let ndc_to_clip = Vector2::new(1.0, (height as f64) / (width as f64));
let clip_zoom_factor = 1.0;
let zoom_factor = 1.0;
let fov = FieldOfView::new(&ndc_to_clip, clip_zoom_factor, &w2m, projection);
let fov = FieldOfView::new(&ndc_to_clip, zoom_factor, &w2m, projection);
let gl = gl.clone();
let is_allsky = true;
@@ -154,7 +165,7 @@ impl CameraViewPort {
// Internal variable used for projection purposes
ndc_to_clip,
clip_zoom_factor,
zoom_factor,
// The field of view
fov,
view_hpx_cells,
@@ -177,6 +188,9 @@ impl CameraViewPort {
coo_sys,
// a flag telling if the viewport has a reversed longitude axis
reversed_longitude,
min_fov: None,
max_fov: None,
}
}
@@ -223,13 +237,13 @@ impl CameraViewPort {
// check the projection
match proj {
ProjectionType::Tan(_) => self.aperture >= 100.0_f64.to_radians().to_angle(),
ProjectionType::Mer(_) => self.aperture >= 120.0_f64.to_radians().to_angle(),
ProjectionType::Stg(_) => self.aperture >= 200.0_f64.to_radians().to_angle(),
ProjectionType::Tan(_) => self.aperture >= 100.0_f64.to_radians(),
ProjectionType::Mer(_) => self.aperture >= 120.0_f64.to_radians(),
ProjectionType::Stg(_) => self.aperture >= 200.0_f64.to_radians(),
ProjectionType::Sin(_) => false,
ProjectionType::Ait(_) => self.aperture >= 100.0_f64.to_radians().to_angle(),
ProjectionType::Mol(_) => self.aperture >= 100.0_f64.to_radians().to_angle(),
ProjectionType::Zea(_) => self.aperture >= 140.0_f64.to_radians().to_angle(),
ProjectionType::Ait(_) => self.aperture >= 100.0_f64.to_radians(),
ProjectionType::Mol(_) => self.aperture >= 100.0_f64.to_radians(),
ProjectionType::Zea(_) => self.aperture >= 140.0_f64.to_radians(),
}
}
@@ -278,12 +292,8 @@ impl CameraViewPort {
// Compute the new clip zoom factor
self.compute_ndc_to_clip_factor(projection);
self.fov.set_aperture(
&self.ndc_to_clip,
self.clip_zoom_factor,
&self.w2m,
projection,
);
self.fov
.set_aperture(&self.ndc_to_clip, self.zoom_factor, &self.w2m, projection);
let proj_area = projection.get_area();
self.is_allsky = !proj_area.is_in(&math::projection::ndc_to_clip_space(
@@ -325,7 +335,74 @@ impl CameraViewPort {
self.set_aperture(self.aperture, proj);
}
pub fn set_aperture(&mut self, aperture: Angle<f64>, proj: &ProjectionType) {
/// Give a FoV range in radians
pub(crate) fn set_fov_range(
&mut self,
mut min_fov: Option<f64>,
mut max_fov: Option<f64>,
proj: &ProjectionType,
) {
// Invert the min and max bounds if min > max
if let (Some(min_fov), Some(max_fov)) = (min_fov.as_mut(), max_fov.as_mut()) {
if *max_fov < *min_fov {
std::mem::swap(max_fov, min_fov);
}
}
self.min_fov = min_fov;
self.max_fov = max_fov;
self.set_aperture(self.aperture, proj);
}
pub(crate) fn at_zoom_boundaries(&self, proj: &ProjectionType) -> bool {
// The zoom factor cannot exceed an upper limit
if self.zoom_factor >= ZOOM_FACTOR_UPPER_LIMIT {
return true;
}
// The field of view cannot go deeper a lower limit
if self.aperture <= APERTURE_LOWER_LIMIT_RAD {
return true;
}
// The field of view might be forced in a user defined range
if let Some(min_fov) = self.min_fov {
if self.aperture <= min_fov {
return true;
}
}
if let Some(max_fov) = self.max_fov {
if self.aperture >= max_fov {
return true;
}
}
let can_unzoom_more = match proj {
ProjectionType::Tan(_) | ProjectionType::Mer(_) | ProjectionType::Stg(_) => false,
_ => true,
};
if !can_unzoom_more && self.zoom_factor >= 1.0 {
return true;
}
false
}
pub(crate) fn set_aperture(&mut self, mut aperture: f64, proj: &ProjectionType) {
// Force the given aperture by a range given by the user
if let Some(min_fov) = self.min_fov {
aperture = aperture.max(min_fov);
}
if let Some(max_fov) = self.max_fov {
aperture = aperture.min(max_fov);
}
// Limit internally the aperture to 0.1 arcsec
aperture = aperture.max(APERTURE_LOWER_LIMIT_RAD);
// Checking if we are zooming or unzooming
// This is used internaly for the raytracer to compute
// blending between tiles and their parents (or children)
@@ -338,23 +415,15 @@ impl CameraViewPort {
};
let can_unzoom_more = match proj {
ProjectionType::Tan(_)
| ProjectionType::Mer(_)
//| ProjectionType::Air(_)
| ProjectionType::Stg(_) => false,
//| ProjectionType::Car(_)
//| ProjectionType::Cea(_)
//| ProjectionType::Cyp(_)
//| ProjectionType::Hpx(_) => false,
ProjectionType::Tan(_) | ProjectionType::Mer(_) | ProjectionType::Stg(_) => false,
_ => true,
};
let aperture_start = proj.aperture_start();
let aperture_start: f64 = proj.aperture_start().to_radians();
self.clip_zoom_factor = if aperture > aperture_start {
//al_core::log(&format!("a: {:?}, as: {:?}", aperture, aperture_start));
self.zoom_factor = if aperture > aperture_start {
if can_unzoom_more {
aperture.to_radians() / aperture_start.to_radians()
aperture / aperture_start
} else {
1.0
}
@@ -362,35 +431,24 @@ impl CameraViewPort {
// Compute the new clip zoom factor
let a = aperture.abs();
let v0 = math::lonlat::radec_to_xyzw(-a / 2.0, 0.0.to_angle());
let v1 = math::lonlat::radec_to_xyzw(a / 2.0, 0.0.to_angle());
let v0 = math::lonlat::radec_to_xyz(-a.to_angle() / 2.0, 0.0.to_angle());
let v1 = math::lonlat::radec_to_xyz(a.to_angle() / 2.0, 0.0.to_angle());
// Vertex in the WCS of the FOV
if self.width < self.height {
if let (Some(p0), Some(p1)) =
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
{
(0.5 * (p1.x - p0.x).abs()).min(1.0)
} else {
1.0
}
if let (Some(p0), Some(p1)) =
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
{
(0.5 * (p1.x - p0.x).abs()).min(1.0)
} else {
if let (Some(p0), Some(p1)) =
(proj.world_to_clip_space(&v0), proj.world_to_clip_space(&v1))
{
(0.5 * (p1.x - p0.x).abs()).min(1.0)
} else {
1.0
}
1.0
}
};
// Limit the zoom factor to not unzoom too much
self.zoom_factor = self.zoom_factor.min(ZOOM_FACTOR_UPPER_LIMIT);
// Limit later the aperture to aperture_start
self.aperture = aperture.min(aperture_start);
//self.aperture = aperture;
//al_core::log(&format!("zoom factor {:?}", self.clip_zoom_factor));
//console_log(&format!("clip factor {:?}", self.aperture));
// Project this vertex into the screen
self.moved = true;
@@ -398,7 +456,101 @@ impl CameraViewPort {
self.time_last_move = Time::now();
self.fov
.set_aperture(&self.ndc_to_clip, self.clip_zoom_factor, &self.w2m, proj);
.set_aperture(&self.ndc_to_clip, self.zoom_factor, &self.w2m, proj);
let proj_area = proj.get_area();
self.is_allsky = !proj_area.is_in(&math::projection::ndc_to_clip_space(
&Vector2::new(-1.0, -1.0),
self,
));
self.compute_texture_depth();
// Recompute the scissor with the new aperture
self.recompute_scissor();
// Compute the hpx cells
self.view_hpx_cells.update(
self.texture_depth,
&self.fov,
&self.center,
self.get_coo_system(),
proj,
);
}
pub(crate) fn set_zoom_factor(&mut self, zoom_factor: f64, proj: &ProjectionType) {
// Checking if we are zooming or unzooming
// This is used internaly for the raytracer to compute
// blending between tiles and their parents (or children)
self.last_user_action = if self.zoom_factor > zoom_factor {
UserAction::Zooming
} else if self.zoom_factor < zoom_factor {
UserAction::Unzooming
} else {
self.last_user_action
};
let can_unzoom_more = match proj {
ProjectionType::Tan(_) | ProjectionType::Mer(_) | ProjectionType::Stg(_) => false,
_ => true,
};
// Set the zoom factor
self.zoom_factor = zoom_factor;
// Limit it to prevent unzooming infinitely
self.zoom_factor = self.zoom_factor.min(ZOOM_FACTOR_UPPER_LIMIT);
let aperture_start = proj.aperture_start().to_radians();
// clamp it to one if we cannot unzoom more (because of the projection)
let aperture = if !can_unzoom_more && zoom_factor >= 1.0 {
self.zoom_factor = 1.0;
aperture_start
} else if can_unzoom_more && zoom_factor >= 1.0 {
aperture_start
} else {
// zoom_factor < 1.0
if let Some((lon, _)) = proj
.clip_to_world_space(&Vector2::new(self.zoom_factor, 0.0))
.map(|xyz| math::lonlat::xyz_to_radec(&xyz))
{
lon.to_radians().abs() * 2.0
} else {
aperture_start
}
};
// Force the given aperture to be in an optional range given by the user
let mut clamped_aperture = aperture;
if let Some(min_fov) = self.min_fov {
clamped_aperture = clamped_aperture.max(min_fov);
}
if let Some(max_fov) = self.max_fov {
clamped_aperture = clamped_aperture.min(max_fov);
}
// The aperture must also be > to a lower limit
clamped_aperture = clamped_aperture.max(APERTURE_LOWER_LIMIT_RAD);
if clamped_aperture != aperture {
// there has been a clamping of the aperture, then we recompute the zoom factor
// with the new clamped aperture
self.set_aperture(clamped_aperture, proj);
return;
}
self.aperture = aperture;
// Project this vertex into the screen
self.moved = true;
self.zoomed = true;
self.time_last_move = Time::now();
self.fov
.set_aperture(&self.ndc_to_clip, self.zoom_factor, &self.w2m, proj);
let proj_area = proj.get_area();
self.is_allsky = !proj_area.is_in(&math::projection::ndc_to_clip_space(
@@ -448,8 +600,7 @@ impl CameraViewPort {
let smallest_cell_size_px = self.dpi as f64;
let mut depth_pixel = 29 as usize;
let hpx_cell_size_rad =
(smallest_cell_size_px / w_screen_px) * self.get_aperture().to_radians();
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 {
@@ -471,7 +622,7 @@ impl CameraViewPort {
self.texture_depth
}
pub fn apply_rotation(
pub fn apply_axis_rotation(
&mut self,
axis: &cgmath::Vector3<f64>,
angle: Angle<f64>,
@@ -484,14 +635,29 @@ impl CameraViewPort {
self.update_rot_matrices(proj);
}
pub fn apply_lonlat_rotation(
&mut self,
dlon: Angle<f64>,
dlat: Angle<f64>,
proj: &ProjectionType
) {
let center = self.get_center();
let rot = Rotation::from_axis_angle(&Vector3::new(center.z, 0.0, -center.x).normalize(), dlat) * Rotation::from_axis_angle(&Vector3::unit_y(), -dlon) * Rotation::from_sky_position(&center);
self.set_rotation(&rot, proj);
}
/// center lonlat must be given in icrs frame
pub fn set_center(&mut self, lonlat: &LonLatT<f64>, proj: &ProjectionType) {
let icrs_pos: Vector4<_> = lonlat.vector();
let icrs_pos = lonlat.vector();
self.set_center_xyz(&icrs_pos, proj);
}
let center = (CooSystem::ICRS.to(self.get_coo_system()) * icrs_pos).truncate();
pub fn set_center_xyz(&mut self, xyz: &Vector3<f64>, proj: &ProjectionType) {
let center = CooSystem::ICRS.to(self.get_coo_system()) * xyz;
let rot_to_center = Rotation::from_sky_position(&center);
let phi = self.get_center_pos_angle();
let phi = self.get_position_angle();
let third_euler_rot = Rotation::from_axis_angle(&center, phi);
let rot = third_euler_rot * rot_to_center;
@@ -501,8 +667,8 @@ impl CameraViewPort {
self.set_rotation(&rot, proj);
}
pub fn set_center_pos_angle(&mut self, phi: Angle<f64>, proj: &ProjectionType) {
let c = self.center.truncate();
pub fn set_position_angle(&mut self, phi: Angle<f64>, proj: &ProjectionType) {
let c = self.center;
let rot_to_center = Rotation::from_sky_position(&c);
let third_euler_rot = Rotation::from_axis_angle(&c, phi);
@@ -510,7 +676,7 @@ impl CameraViewPort {
self.set_rotation(&total_rot, proj);
}
fn set_rotation(&mut self, rot: &Rotation<f64>, proj: &ProjectionType) {
pub fn set_rotation(&mut self, rot: &Rotation<f64>, proj: &ProjectionType) {
self.w2m_rot = *rot;
self.update_rot_matrices(proj);
@@ -524,7 +690,7 @@ impl CameraViewPort {
// Compute the center position according to the new coordinate frame system
let new_center = coosys::apply_coo_system(self.coo_sys, new_coo_sys, &self.center);
// Create a rotation object from that position
let new_rotation = Rotation::from_sky_position(&new_center.truncate());
let new_rotation = Rotation::from_sky_position(&new_center);
// Apply it to the center of the view
self.set_rotation(&new_rotation, proj);
@@ -565,11 +731,11 @@ impl CameraViewPort {
}
// Accessors
pub fn get_w2m(&self) -> &cgmath::Matrix4<f64> {
pub fn get_w2m(&self) -> &cgmath::Matrix3<f64> {
&self.w2m
}
pub fn get_m2w(&self) -> &cgmath::Matrix4<f64> {
pub fn get_m2w(&self) -> &cgmath::Matrix3<f64> {
&self.m2w
}
@@ -581,11 +747,11 @@ impl CameraViewPort {
&self.ndc_to_clip
}
pub fn get_clip_zoom_factor(&self) -> f64 {
self.clip_zoom_factor
pub fn get_zoom_factor(&self) -> f64 {
self.zoom_factor
}
pub fn get_vertices(&self) -> Option<&Vec<XYZWModel<f64>>> {
pub fn get_vertices(&self) -> Option<&Vec<XYZModel<f64>>> {
self.fov.get_vertices()
}
@@ -623,13 +789,14 @@ impl CameraViewPort {
self.zoomed = false;
}
/// Aperture is given in radians
#[inline]
pub fn get_aperture(&self) -> Angle<f64> {
pub fn get_aperture(&self) -> f64 {
self.aperture
}
#[inline]
pub fn get_center(&self) -> &Vector4<f64> {
pub fn get_center(&self) -> &Vector3<f64> {
&self.center
}
@@ -646,7 +813,7 @@ impl CameraViewPort {
self.coo_sys
}
pub fn get_center_pos_angle(&self) -> Angle<f64> {
pub fn get_position_angle(&self) -> Angle<f64> {
(self.w2m.x.y).atan2(self.w2m.y.y).to_angle()
}
}
@@ -688,7 +855,7 @@ impl SendUniforms for CameraViewPort {
fn attach_uniforms<'a>(&self, shader: &'a ShaderBound<'a>) -> &'a ShaderBound<'a> {
shader
.attach_uniform("ndc_to_clip", &self.ndc_to_clip) // Send ndc to clip
.attach_uniform("czf", &self.clip_zoom_factor); // Send clip zoom factor
.attach_uniform("czf", &self.zoom_factor); // Send clip zoom factor
shader
}

View File

@@ -1,4 +1,4 @@
use cgmath::Vector4;
use cgmath::Vector3;
use al_api::coo_system::CooSystem;
/// This is conversion method returning a transformation
@@ -6,7 +6,7 @@ use al_api::coo_system::CooSystem;
/// ICRS.
/// The core projections are always performed in ICRS
#[inline]
pub fn apply_coo_system(c1: CooSystem, c2: CooSystem, v: &Vector4<f64>) -> Vector4<f64> {
pub fn apply_coo_system(c1: CooSystem, c2: CooSystem, v: &Vector3<f64>) -> Vector3<f64> {
let c1_2_c2_mat = c1.to(c2);
c1_2_c2_mat * (*v)
}

View File

@@ -185,14 +185,24 @@ impl From<query::Allsky> for AllskyRequest {
.collect())
}
InMemData::F32(data) => {
let data = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 4) };
let data = unsafe {
std::slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * 4,
)
};
Ok(handle_allsky_fits(&data, tile_size, texture_size)?
.map(|image| ImageType::RawRgba8u { image })
.collect())
}
InMemData::F64(data) => {
let data = data.iter().map(|v| *v as f32).collect::<Vec<_>>();
let data = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * 4) };
let data = unsafe {
std::slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * 4,
)
};
Ok(handle_allsky_fits(&data, tile_size, texture_size)?
.map(|image| ImageType::RawRgba8u { image })
@@ -228,71 +238,77 @@ fn handle_allsky_file<F: ImageFormat>(
let num_allsky_tiles_per_tile = (tile_size / allsky_tile_size) * (tile_size / allsky_tile_size);
let mut src_idx = 0;
let tiles = (0..num_tiles)
.map(move |_| {
let mut base_tile =
let tiles = (0..num_tiles).map(move |_| {
let mut base_tile =
ImageBuffer::<F>::allocate(&<F as ImageFormat>::P::BLACK, tile_size, tile_size);
for idx_tile in 0..num_allsky_tiles_per_tile {
let (x, y) = crate::utils::unmortonize(idx_tile as u64);
let dx = x * (allsky_tile_size as u32);
let dy = y * (allsky_tile_size as u32);
for idx_tile in 0..num_allsky_tiles_per_tile {
let (x, y) = crate::utils::unmortonize(idx_tile as u64);
let dx = x * (allsky_tile_size as u32);
let dy = y * (allsky_tile_size as u32);
let sx = (src_idx % 27) * allsky_tile_size;
let sy = (src_idx / 27) * allsky_tile_size;
let s = ImageBufferView {
x: sx as i32,
y: sy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
let d = ImageBufferView {
x: dx as i32,
y: dy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
let sx = (src_idx % 27) * allsky_tile_size;
let sy = (src_idx / 27) * allsky_tile_size;
let s = ImageBufferView {
x: sx as i32,
y: sy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
let d = ImageBufferView {
x: dx as i32,
y: dy as i32,
w: allsky_tile_size as i32,
h: allsky_tile_size as i32,
};
base_tile.tex_sub(&allsky, &s, &d);
base_tile.tex_sub(&allsky, &s, &d);
src_idx += 1;
}
src_idx += 1;
}
base_tile
});
base_tile
});
Ok(tiles)
}
fn handle_allsky_fits<F: ImageFormat>(
allsky_data: &[<<F as ImageFormat>::P as Pixel>::Item],
tile_size: i32,
texture_size: i32,
) -> Result<impl Iterator<Item=ImageBuffer<F>>, JsValue> {
) -> Result<impl Iterator<Item = ImageBuffer<F>>, JsValue> {
let allsky_tile_size = std::cmp::min(tile_size, 64);
let width_allsky_px = 27 * allsky_tile_size;
let height_allsky_px = 29 * allsky_tile_size;
// The fits image layout stores rows in reverse
let reversed_rows_data = allsky_data
.chunks(width_allsky_px as usize)
.chunks(width_allsky_px as usize * F::NUM_CHANNELS)
.rev()
.flatten()
.copied()
.collect::<Vec<_>>();
let allsky = ImageBuffer::<F>::new(reversed_rows_data, width_allsky_px, height_allsky_px);
let allsky_tiles_iter = handle_allsky_file::<F>(allsky, allsky_tile_size, texture_size, tile_size)?
.map(move |image| {
// The GPU does a specific transformation on the UV
// for FITS tiles
// We must revert this to be compatible with this GPU transformation
let mut new_image_data = Vec::with_capacity(tile_size as usize);
for c in image.get_data().chunks((tile_size * tile_size) as usize) {
new_image_data.extend(c.chunks(tile_size as usize).rev().flatten());
}
let allsky_tiles_iter =
handle_allsky_file::<F>(allsky, allsky_tile_size, texture_size, tile_size)?.map(
move |image| {
// The GPU does a specific transformation on the UV for FITS tiles
// We must revert this to be compatible with this GPU transformation
let new_image_data = image
.get_data()
.chunks((tile_size * tile_size) as usize * F::NUM_CHANNELS)
.flat_map(|c| {
c.chunks(tile_size as usize * F::NUM_CHANNELS)
.rev()
.flatten()
})
.cloned()
.collect();
ImageBuffer::<F>::new(new_image_data, tile_size, tile_size)
});
ImageBuffer::<F>::new(new_image_data, tile_size, tile_size)
},
);
Ok(allsky_tiles_iter)
}

View File

@@ -76,15 +76,20 @@ impl HEALPixCell {
}
#[inline(always)]
pub fn idx(&self) -> u64 {
pub(crate) const fn idx(&self) -> u64 {
self.1
}
#[inline(always)]
pub fn depth(&self) -> u8 {
pub(crate) const fn depth(&self) -> u8 {
self.0
}
#[inline(always)]
pub fn nside(&self) -> u64 {
1 << self.depth()
}
#[inline(always)]
pub fn is_root(&self) -> bool {
self.depth() == 0
@@ -168,6 +173,19 @@ impl HEALPixCell {
HEALPixTilesIter::new(depth_children, first_idx..last_idx)
}
#[inline]
pub(crate) const fn subdivide(&self) -> [HEALPixCell; 4] {
let children_depth = self.depth() + 1;
let children_idx = self.idx() << 2;
[
HEALPixCell(children_depth, children_idx),
HEALPixCell(children_depth, children_idx + 1),
HEALPixCell(children_depth, children_idx + 2),
HEALPixCell(children_depth, children_idx + 3),
]
}
#[inline]
pub fn allsky(depth: u8) -> impl Iterator<Item = HEALPixCell> {
let npix = 12 << ((depth as usize) << 1);
@@ -193,7 +211,7 @@ impl HEALPixCell {
}
#[inline(always)]
pub fn is_on_pole(&self) -> bool {
pub(crate) fn is_on_pole(&self) -> bool {
let HEALPixCell(depth, idx) = *self;
let two_times_depth = 2 * depth;
@@ -207,6 +225,40 @@ impl HEALPixCell {
}
}
#[inline(always)]
pub(crate) fn has_7_neigh(&self) -> bool {
let base_cell = self.ancestor(self.depth());
let nside_minus_one = (self.nside() - 1) as u32;
let (x, y) = self.offset_in_parent(&base_cell);
match base_cell.idx() {
0..=3 => (x == 0 && y == nside_minus_one) || (y == 0 && x == nside_minus_one),
4..=7 => (x == 0 && y == 0) || (x == nside_minus_one && y == nside_minus_one),
8..=11 => (x == 0 && y == nside_minus_one) || (y == 0 && x == nside_minus_one),
_ => unreachable!()
}
}
#[inline(always)]
pub(crate) fn is_on_base_cell_edges(&self) -> bool {
let base_cell = self.ancestor(self.depth());
let nside_minus_one = (self.nside() - 1) as u32;
let (x, y) = self.offset_in_parent(&base_cell);
if x == 0 || x == nside_minus_one {
return true;
}
if y == 0 || y == nside_minus_one {
return true;
}
false
}
// Given in ICRS
#[inline]
pub fn new(depth: u8, theta: f64, delta: f64) -> Self {

View File

@@ -2,7 +2,7 @@ use crate::math::lonlat::LonLatT;
use crate::math::PI;
use crate::math::{self, lonlat::LonLat};
use cgmath::{Vector4};
use cgmath::Vector3;
use moclib::{
moc::range::{CellSelection, RangeMOC},
qty::Hpx,
@@ -81,8 +81,8 @@ impl HEALPixCoverage {
HEALPixCoverage(moc)
}
pub fn contains_coo(&self, coo: &Vector4<f64>) -> bool {
let (lon, lat) = math::lonlat::xyzw_to_radec(coo);
pub fn contains_coo(&self, coo: &Vector3<f64>) -> bool {
let (lon, lat) = math::lonlat::xyz_to_radec(coo);
self.0.is_in(lon.to_radians(), lat.to_radians())
}

View File

@@ -4,7 +4,6 @@ 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
@@ -14,15 +13,17 @@ pub struct Inertia {
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>) -> Self {
pub fn new(ampl: f64, axis: Vector3<f64>, north_up: bool) -> Self {
Inertia {
time_start: Time::now(),
ampl: ampl,
ampl,
speed: ampl,
axis: axis,
axis,
north_up
}
}
@@ -35,7 +36,7 @@ impl Inertia {
// where:
// * k is the stiffness of the ressort
// * m is its mass
let w0 = 10.0;
let w0 = 7.0;
// The angular distance goes from d0 to 0.0
//self.speed = self.ampl * ((-w0 * t).exp());
// The angular distance goes from d0 to 0.0
@@ -43,7 +44,11 @@ impl Inertia {
/*let alpha = 1_f32 + (0_f32 - 1_f32) * (10_f32 * t + 1_f32) * (-10_f32 * t).exp();
let alpha = alpha * alpha;
let fov = start_fov * (1_f32 - alpha) + goal_fov * alpha;*/
camera.apply_rotation(&self.axis, self.speed.to_angle(), proj)
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 get_start_ampl(&self) -> f64 {

View File

@@ -130,7 +130,7 @@ use al_core::Colormap;
use al_core::WebGlContext;
use app::App;
use cgmath::{Vector2, Vector4};
use cgmath::{Vector2, Vector3};
use crate::healpix::cell::HEALPixCell;
use math::angle::ArcDeg;
@@ -469,6 +469,12 @@ impl WebClient {
Ok(fov)
}
/// Get the max aperture of a projection (in degrees)
#[wasm_bindgen(js_name = atZoomBoundaries)]
pub fn get_max_aperture(&self) -> bool {
self.app.camera.at_zoom_boundaries(&self.app.projection)
}
/// Set the field of view
///
/// # Arguments
@@ -476,13 +482,12 @@ impl WebClient {
/// * `fov` - The field of view in degrees
#[wasm_bindgen(js_name = setFieldOfView)]
pub fn set_fov(&mut self, fov: f64) -> Result<(), JsValue> {
let fov = ArcDeg(fov).into();
self.app.set_fov(fov);
self.app.set_fov(fov.to_radians());
Ok(())
}
/// Enable/Disable inertia effect after panning and releasing the mouse
#[wasm_bindgen(js_name = setInertia)]
pub fn set_inertia(&mut self, inertia: bool) -> Result<(), JsValue> {
self.app.set_inertia(inertia);
@@ -490,23 +495,57 @@ impl WebClient {
Ok(())
}
/// Set a range of FoVs that contrains the zooming in that range
///
/// # Arguments
///
/// * `min_fov` - The minimum field of view value in degrees
/// * `max_fov` - The maximum field of view value in degrees
#[wasm_bindgen(js_name = setFoVRange)]
pub fn set_fov_range(
&mut self,
min_fov: Option<f64>,
max_fov: Option<f64>,
) -> Result<(), JsValue> {
self.app.set_fov_range(min_fov, max_fov);
Ok(())
}
/// Get the FoV range in degrees
#[wasm_bindgen(js_name = getFoVRange)]
pub fn get_fov_range(&self) -> Box<[f64]> {
Box::new([
self.app
.camera
.min_fov
.map(|v| v.to_degrees())
.unwrap_or(-1.0),
self.app
.camera
.max_fov
.map(|v| v.to_degrees())
.unwrap_or(-1.0),
])
}
/// Set the absolute orientation of the view
///
/// # Arguments
///
/// * `theta` - The rotation angle in degrees
#[wasm_bindgen(js_name = setViewCenter2NorthPoleAngle)]
pub fn set_view_center_pos_angle(&mut self, theta: f64) -> Result<(), JsValue> {
#[wasm_bindgen(js_name = setRotation)]
pub fn set_rotation(&mut self, theta: f64) -> Result<(), JsValue> {
let theta = ArcDeg(theta);
self.app.set_view_center_pos_angle(theta);
self.app.set_position_angle(theta);
Ok(())
}
/// Get the absolute orientation angle of the view
#[wasm_bindgen(js_name = getViewCenter2NorthPoleAngle)]
pub fn get_north_shift_angle(&mut self) -> Result<f64, JsValue> {
let phi = self.app.get_north_shift_angle();
#[wasm_bindgen(js_name = getRotation)]
pub fn get_rotation(&mut self) -> Result<f64, JsValue> {
let phi = self.app.get_position_angle();
Ok(phi.to_degrees())
}
@@ -537,14 +576,20 @@ impl WebClient {
self.app.get_max_fov().to_degrees()
}
/// Get the clip zoom factor of the view
/// Get the zoom factor of the view
///
/// This factor is deduced from the field of view angle.
/// It is a constant which when multiplied to the screen coordinates
/// gives the coordinates in clipping space.
#[wasm_bindgen(js_name = getClipZoomFactor)]
pub fn get_clip_zoom_factor(&self) -> Result<f64, JsValue> {
Ok(self.app.get_clip_zoom_factor())
#[wasm_bindgen(js_name = getZoomFactor)]
pub fn get_zoom_factor(&self) -> Result<f64, JsValue> {
Ok(self.app.get_zoom_factor())
}
/// Set the zoom factor of the view
#[wasm_bindgen(js_name = setZoomFactor)]
pub fn set_zoom_factor(&mut self, zoom_factor: f64) -> Result<(), JsValue> {
Ok(self.app.set_zoom_factor(zoom_factor))
}
/// Set the center of the view in ICRS coosys
@@ -565,6 +610,11 @@ impl WebClient {
Ok(())
}
#[wasm_bindgen(js_name = lockNorthUp)]
pub fn lock_north_up(&mut self) {
self.app.lock_north_up();
}
/// Get the center of the view
///
/// This returns a javascript array of size 2.
@@ -1059,12 +1109,12 @@ impl WebClient {
let vertex_it = ra_deg
.iter()
.zip(dec_deg.iter())
.map(|(ra, dec)| -> Vector4<f64> {
.map(|(ra, dec)| -> Vector3<f64> {
let lonlat = LonLatT(ra.to_radians().to_angle(), dec.to_radians().to_angle());
lonlat.vector()
});
let v_in = &Vector4::new(1.0, 0.0, 0.0, 1.0);
let v_in = &Vector3::new(1.0, 0.0, 0.0);
let mut moc = HEALPixCoverage::from_3d_coos(pixel_d as u8 - 1, vertex_it, &v_in);
if moc.sky_fraction() > 0.5 {

View File

@@ -145,15 +145,6 @@ where
#[derive(Clone, Copy)]
pub struct ArcSec<T: BaseFloat>(pub T);
impl<T> ArcSec<T>
where
T: BaseFloat,
{
fn _truncate(&mut self) {
*self = Self((*self).trunc());
}
}
impl<T> From<Rad<T>> for ArcSec<T>
where
T: BaseFloat,
@@ -409,7 +400,7 @@ where
S::max_value().to_angle()
}
pub fn to_radians(&self) -> S {
pub const fn to_radians(&self) -> S {
self.rad
}

Some files were not shown because too many files have changed in this diff Show More