use super::{DatumParams, DatumType, ParameterValue};
use crate::proj::{
AZIMUTH_PROJECTION_CENTRE, FALSE_EASTING, FALSE_NORTHING, LATITUDE_OF_FALSE_ORIGIN,
LATITUDE_OF_NATURAL_ORIGIN, LATITUDE_OF_PROJECTION_CENTRE, LONGITUDE_OF_FALSE_ORIGIN,
LONGITUDE_OF_NATURAL_ORIGIN, LONGITUDE_OF_PROJECTION_CENTRE, ProjValue,
SCALE_FACTOR_AT_NATURAL_ORIGIN, name_to_param_id,
};
use alloc::{collections::BTreeMap, string::String};
use s2json::{GetXY, GetZ, NewXY, NewXYZ, SetXY, SetZ};
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct Coords(pub f64, pub f64, pub f64, pub f64);
impl Coords {
pub fn new(x: f64, y: f64, z: f64, t: f64) -> Coords {
Coords(x, y, z, t)
}
pub fn new_xy(x: f64, y: f64) -> Coords {
Coords(x, y, 0.0, 0.0)
}
}
impl GetXY for Coords {
fn x(&self) -> f64 {
self.0
}
fn y(&self) -> f64 {
self.1
}
}
impl GetZ for Coords {
fn z(&self) -> Option<f64> {
Some(self.2)
}
}
impl NewXY for Coords {
fn new_xy(x: f64, y: f64) -> Self {
Coords(x, y, 0.0, 0.0)
}
}
impl NewXYZ for Coords {
fn new_xyz(x: f64, y: f64, z: f64) -> Self {
Coords(x, y, z, 0.0)
}
}
impl SetXY for Coords {
fn set_x(&mut self, x: f64) {
self.0 = x;
}
fn set_y(&mut self, y: f64) {
self.1 = y;
}
}
impl SetZ for Coords {
fn set_z(&mut self, z: f64) {
self.2 = z;
}
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct Complex {
pub r: f64,
pub i: f64,
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub enum ProjMethod {
#[default]
Ellipsoidal = 0,
Spheroidal = 1,
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub enum ProjMode {
#[default]
NPole = 0,
SPole = 1,
Equit = 2,
Obliq = 3,
}
#[derive(Debug, Clone, PartialEq)]
#[allow(non_snake_case)]
pub struct Proj {
pub name: String,
pub params: BTreeMap<i64, ProjValue>,
pub ellps: String,
pub a: f64,
pub b: f64,
pub ra: f64,
pub rb: f64,
pub sphere: bool,
pub alpha: f64,
pub e: f64,
pub es: f64,
pub e2: f64,
pub e2s: f64,
pub e3: f64,
pub e3s: f64,
pub one_es: f64,
pub rone_es: f64,
pub f: f64,
pub f2: f64,
pub n: f64,
pub rf: f64,
pub rf2: f64,
pub rn: f64,
pub J: f64,
pub es_orig: f64,
pub a_orig: f64,
pub over: bool,
pub geoc: bool,
pub is_ll: bool,
pub is_geocent: bool,
pub left: IoUnits,
pub right: IoUnits,
pub lam0: f64,
pub phi0: f64,
pub x0: f64,
pub y0: f64,
pub z0: f64,
pub t0: f64,
pub k0: f64,
pub to_meter: f64,
pub fr_meter: f64,
pub vto_meter: f64,
pub vfr_meter: f64,
pub datum_type: DatumType,
pub datum_params: DatumParams,
pub from_greenwich: f64,
}
impl Default for Proj {
fn default() -> Self {
Self {
name: "".into(),
params: BTreeMap::new(),
ellps: "".into(),
a: 0.,
b: 0.,
ra: 0.,
rb: 0.,
sphere: false,
alpha: 0.,
e: 0.,
es: 0.,
e2: 0.,
e2s: 0.,
e3: 0.,
e3s: 0.,
one_es: 0.,
rone_es: 0.,
f: 0.,
f2: 0.,
n: 0.,
rf: 0.,
rf2: 0.,
rn: 0.,
J: 0.,
es_orig: 0.,
a_orig: 0.,
over: false,
geoc: false,
is_ll: false,
is_geocent: false,
left: IoUnits::RADIANS,
right: IoUnits::CLASSIC,
lam0: 0.,
phi0: 0.,
x0: 0.,
y0: 0.,
z0: 0.,
t0: 0.,
k0: 1.,
to_meter: 1.,
fr_meter: 1.,
vto_meter: 1.,
vfr_meter: 1.,
datum_type: DatumType::NoDatum,
datum_params: DatumParams::default(),
from_greenwich: 0.,
}
}
}
impl Proj {
pub fn add_param(&mut self, param: &ParameterValue) {
if let Some(id) = ¶m.id {
self.insert_param(id.code.i64(), param.into());
} else if !param.ids.is_empty() {
for id in ¶m.ids {
self.insert_param(id.code.i64(), param.into());
}
} else {
self.insert_param(name_to_param_id(¶m.name), param.into());
}
}
pub fn set_f64(&mut self, id: i64, value: f64) {
self.insert_param(id, value.into());
}
fn insert_param(&mut self, id: i64, value: ProjValue) {
self.add_to_params(id, &value);
self.params.insert(id, value);
}
fn add_to_params(&mut self, id: i64, value: &ProjValue) {
match id {
LONGITUDE_OF_FALSE_ORIGIN
| LONGITUDE_OF_NATURAL_ORIGIN
| LONGITUDE_OF_PROJECTION_CENTRE => self.lam0 = value.f64(),
LATITUDE_OF_FALSE_ORIGIN
| LATITUDE_OF_NATURAL_ORIGIN
| LATITUDE_OF_PROJECTION_CENTRE => self.phi0 = value.f64(),
SCALE_FACTOR_AT_NATURAL_ORIGIN => self.k0 = value.f64(),
AZIMUTH_PROJECTION_CENTRE => self.alpha = value.f64(),
FALSE_EASTING => self.x0 = value.f64(),
FALSE_NORTHING => self.y0 = value.f64(),
_ => {}
}
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub enum Direction {
FWD = 1,
#[default]
IDENT = 0,
INV = -1,
}
#[derive(Debug, Default, Clone, PartialEq)]
pub enum IoUnits {
#[default]
WHATEVER = 0,
CLASSIC = 1,
PROJECTED = 2,
CARTESIAN = 3,
RADIANS = 4,
DEGREES = 5,
}