#[derive(Clone)]
pub struct Projection
{
projection_utm: proj4rs::proj::Proj,
projection_wgs84: proj4rs::proj::Proj,
offset_x: f64,
offset_y: f64,
}
fn utm_zone(lon: f64, lat: f64) -> i32
{
if (56.0..64.0).contains(&lat) && (3.0..12.0).contains(&lon)
{
return 32;
}
else if (72.0..84.0).contains(&lat)
{
if (0.0..9.0).contains(&lon)
{
return 31;
}
else if (9.0..21.0).contains(&lon)
{
return 33;
}
else if (21.0..33.0).contains(&lon)
{
return 35;
}
else if (33.0..42.0).contains(&lon)
{
return 37;
}
}
((lon + 180.0) / 6.0) as i32 + 1
}
impl Projection
{
pub fn new(lon: f64, lat: f64) -> Projection
{
let utm_z: i32 = utm_zone(lon, lat);
let proj_str = format!(
"+proj=utm +zone={} +datum=WGS84 +units=m +no_defs +type=crs",
utm_z
);
let proj_from = proj4rs::proj::Proj::from_proj_string(&proj_str[..]).unwrap();
let proj_to = proj4rs::proj::Proj::from_proj_string(concat!(
"+proj=longlat +ellps=WGS84",
" +datum=WGS84 +no_defs"
))
.unwrap();
let mut point_3d = (lon.to_radians(), lat.to_radians(), 0.0);
proj4rs::transform::transform(&proj_to, &proj_from, &mut point_3d).unwrap();
Projection {
projection_utm: proj_from,
projection_wgs84: proj_to,
offset_x: point_3d.0,
offset_y: point_3d.1,
}
}
pub fn from_wgs84(&self, lon: f64, lat: f64) -> (f64, f64)
{
let mut point_3d = (lon.to_radians(), lat.to_radians(), 0.0);
proj4rs::transform::transform(&self.projection_wgs84, &self.projection_utm, &mut point_3d)
.unwrap();
(point_3d.0 - self.offset_x, point_3d.1 - self.offset_y)
}
pub fn to_wgs84(&self, x: f64, y: f64) -> (f64, f64)
{
let mut point_3d = (x + self.offset_x, y + self.offset_y, 0.0);
proj4rs::transform::transform(&self.projection_utm, &self.projection_wgs84, &mut point_3d)
.unwrap();
(point_3d.0.to_degrees(), point_3d.1.to_degrees())
}
}