pub struct OrthoProj<T: Clone> {
_data: Vec<T>,
_lat: f32,
_lon: f32,
_size: u32,
}
impl<T: Clone> OrthoProj<T> {
pub fn new(size: u32, lat: f32, lon: f32, default: T) -> Self {
let s = size as usize;
OrthoProj{ _size: size, _data: vec![default; s*s], _lat: lat.to_radians(), _lon: lon.to_radians() }
}
pub fn new_with_bg(size: u32, lat: f32, lon: f32, bg: T, surface: T) -> Self {
let mut o = Self::new(size, lat, lon, bg);
let r2 = (size/2)*(size/2);
let cx = size/2;
let cy = size/2;
for x in 0..size {
for y in 0..size {
let dist2 = (x-cx)*(x-cx) + (y-cy)*(y-cy);
if dist2 <= r2 {
o.set_pixel(x, y, surface.clone());
}
}
}
o
}
pub fn xy_for_pos(&self, lat: f32, lon: f32) -> Option<(u32, u32)> {
let lat = lat.to_radians();
let lon = lon.to_radians();
let cos_c = self._lat.sin() * lat.sin() + self._lat.cos()*lat.cos()*(lon - self._lon).cos();
if cos_c < 0. {
return None;
}
let r = (self._size / 2) as f32;
let x = r * lat.cos() * (lon - self._lon).sin();
let y = r * ( self._lat.cos()*lat.sin() - self._lat.sin()*lat.cos()*(lon - self._lon).cos() );
let y = y * -1.;
let x = x + r;
let y = y + r;
let x = x.trunc() as u32;
let y = y.trunc() as u32;
Some((x, y))
}
pub fn set(&mut self, lat: f32, lon: f32, value: T) {
match self.xy_for_pos(lat, lon) {
None => {},
Some((x, y)) => {
self.set_pixel(x, y, value);
},
};
}
pub fn get(&self, lat: f32, lon: f32) -> &T {
let r = (self._size / 2) as f32;
let x = r * lat.to_radians().cos() * (lon - self._lon).to_radians().sin();
let y = r * ( self._lon.to_radians().cos()*lat.to_radians().sin() - self._lon.to_radians().sin()*(lon - self._lat).to_radians().cos() );
let i = x.trunc() as usize * self._size as usize + y.trunc() as usize;
&self._data[i]
}
pub fn get_pixel(&self, x: u32, y: u32) -> &T {
&self._data[(x*self._size+y) as usize]
}
fn set_pixel(&mut self, x: u32, y: u32, value: T) {
let i = x as usize * self._size as usize + y as usize;
self._data[i] = value;
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_simple() {
use super::OrthoProj;
let o = OrthoProj::new(3, 0., 0., 0u8);
assert_eq!(o.get_pixel(0, 0), &0u8);
}
}