Files
aladin-lite/src/core/src/survey/view.rs
2022-10-06 10:47:58 +02:00

242 lines
7.0 KiB
Rust

use crate::{coosys, healpix::cell::HEALPixCell, math};
use std::collections::HashMap;
/*
use crate::math::angle::Angle;
use crate::Projection;
use cgmath::Vector2;
pub fn project_vertices<P: Projection>(cell: &HEALPixCell, camera: &CameraViewPort) -> [Vector2<f64>; 4] {
let project_vertex = |(lon, lat): (f64, f64)| -> Vector2<f64> {
let vertex = crate::math::lonlat::radec_to_xyzw(Angle(lon), Angle(lat));
P::view_to_screen_space(&vertex, camera).unwrap()
};
let vertices = cell.vertices();
[
project_vertex(vertices[0]),
project_vertex(vertices[1]),
project_vertex(vertices[2]),
project_vertex(vertices[3])
]
}*/
// Compute a depth from a number of pixels on screen
pub fn depth_from_pixels_on_screen(camera: &CameraViewPort, num_pixels: i32) -> u8 {
let width = camera.get_screen_size().x;
let aperture = camera.get_aperture().0 as f32;
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).round() 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
let depth_offset_texture = math::utils::log_2_unchecked(num_pixels);
// The depth of the texture corresponds to the depth of a pixel
// minus the offset depth of the texture
if depth_offset_texture > depth_pixel {
0_u8
} else {
(depth_pixel - depth_offset_texture) as u8
}
/*let mut depth = 0;
let mut d1 = std::f64::MAX;
let mut d2 = std::f64::MAX;
while d1 > 512.0*512.0 && d2 > 512.0*512.0 {
let (lon, lat) = crate::math::lonlat::xyzw_to_radec(camera.get_center());
let lonlat = math::lonlat::LonLatT(lon, lat);
let (ipix, _, _) = crate::healpix::utils::hash_with_dxdy(depth, &lonlat);
let vertices = project_vertices::<P>(&HEALPixCell(depth, ipix), camera);
d1 = crate::math::vector::dist2(&vertices[0], &vertices[2]);
d2 = crate::math::vector::dist2(&vertices[1], &vertices[3]);
depth += 1;
}
al_core::info!(depth);
if depth > 0 {
depth - 1
} else {
0
}*/
}
use healpix::coverage::HEALPixCoverage;
pub fn compute_view_coverage(camera: &CameraViewPort, depth: u8, dst_frame: &CooSystem) -> HEALPixCoverage {
if depth <= 1 {
HEALPixCoverage::allsky(depth)
} else {
if let Some(vertices) = camera.get_vertices() {
// The vertices coming from the camera are in a specific coo sys
// but cdshealpix accepts them to be given in ICRSJ2000 coo sys
let camera_frame = camera.get_system();
let vertices = vertices
.iter()
.map(|v| coosys::apply_coo_system(camera_frame, dst_frame, v))
.collect::<Vec<_>>();
let inside_vertex = camera.get_center();
let inside_vertex = coosys::apply_coo_system(camera_frame, &dst_frame, &inside_vertex);
// Prefer to query from_polygon with depth >= 2
HEALPixCoverage::new(
depth,
&vertices[..],
&inside_vertex.truncate(),
)
} else {
HEALPixCoverage::allsky(depth)
}
}
}
use crate::healpix;
use al_api::coo_system::CooSystem;
pub fn get_tile_cells_in_camera(
depth_tile: u8,
camera: &CameraViewPort,
hips_frame: &CooSystem,
) -> (HEALPixCoverage, Vec<HEALPixCell>) {
let moc = compute_view_coverage(camera, depth_tile, &hips_frame);
let cells = moc.flatten_to_fixed_depth_cells()
.map(|idx| {
HEALPixCell(depth_tile, idx)
})
.collect();
(moc, cells)
}
// Contains the cells being in the FOV for a specific
pub struct HEALPixCellsInView {
// The set of cells being in the current view for a
// specific image survey
pub depth: u8,
prev_depth: u8,
view_unchanged: bool,
frame: CooSystem,
// flags associating true to cells that
// are new in the fov
cells: HashMap<HEALPixCell, bool>,
// A flag telling whether there has been
// new cells added from the last frame
is_new_cells_added: bool,
coverage: HEALPixCoverage,
}
use crate::camera::CameraViewPort;
impl HEALPixCellsInView {
pub fn new() -> Self {
let cells = HashMap::new();
let coverage = HEALPixCoverage::allsky(0);
let view_unchanged = false;
let frame = CooSystem::ICRSJ2000;
Self {
cells,
prev_depth: 0,
depth: 0,
is_new_cells_added: false,
view_unchanged,
frame,
coverage,
}
}
pub fn reset_frame(&mut self) {
self.is_new_cells_added = false;
self.view_unchanged = false;
self.prev_depth = self.get_depth();
}
// This method is called whenever the user does an action
// that moves the camera.
// Everytime the user moves or zoom, the views must be updated
// The new cells obtained are used for sending new requests
pub fn refresh(&mut self, new_depth: u8, hips_frame: CooSystem, camera: &CameraViewPort) {
self.depth = new_depth;
self.frame = hips_frame;
// Get the cells of that depth in the current field of view
let (coverage, tile_cells) = get_tile_cells_in_camera(self.depth, camera, &self.frame);
self.coverage = coverage;
// Update cells in the fov
self.update_cells_in_fov(&tile_cells);
}
fn update_cells_in_fov(&mut self, cells_in_fov: &[HEALPixCell]) {
let new_cells = cells_in_fov
.iter()
.map(|cell| {
let new = !self.cells.contains_key(cell);
self.is_new_cells_added |= new;
(*cell, new)
})
.collect::<HashMap<_, _>>();
// If no new cells have been added
self.view_unchanged = !self.is_new_cells_added && new_cells.len() == self.cells.len();
self.cells = new_cells;
}
// Accessors
#[inline]
pub fn get_cells(&self) -> impl Iterator<Item = &HEALPixCell> {
self.cells.keys()
}
#[inline]
pub fn num_of_cells(&self) -> usize {
self.cells.len()
}
#[inline]
pub fn get_depth(&self) -> u8 {
self.depth
}
#[inline]
pub fn get_frame(&self) -> &CooSystem {
&self.frame
}
#[inline]
pub fn is_new(&self, cell: &HEALPixCell) -> bool {
if let Some(&is_cell_new) = self.cells.get(cell) {
is_cell_new
} else {
false
}
}
#[inline]
pub fn get_coverage(&self) -> &HEALPixCoverage {
&self.coverage
}
#[inline]
pub fn is_there_new_cells_added(&self) -> bool {
//self.new_cells.is_there_new_cells_added()
self.is_new_cells_added
}
#[inline]
pub fn has_view_changed(&self) -> bool {
//self.new_cells.is_there_new_cells_added()
!self.view_unchanged
}
}