use std::ops::{Add,Sub};
use std::fmt;
#[derive(Debug, Clone, Copy)]
pub struct Ring360(pub f64);
impl Ring360 {
pub const BASE:f64 = 360.0;
pub fn from_gis(lng180: f64) -> Ring360 {
if lng180 < 0.0 {
Ring360(Self::BASE + lng180)
} else {
Ring360(lng180)
}
}
#[deprecated(since="0.2.3", note="please use `from_gis()` instead")]
pub fn from_180(lng180: f64) -> Ring360 {
Self::from_gis(lng180)
}
pub fn degrees(&self) -> f64 {
let deg_val = self.0 % Self::BASE;
if deg_val < 0.0 {
Self::BASE - (0.0 - deg_val)
} else {
deg_val
}
}
pub fn to_f64(&self) -> f64 {
self.degrees()
}
#[deprecated(since="0.1.0", note="please use `degrees()` instead")]
pub fn degree(&self) -> f64 {
self.degrees()
}
pub fn to_gis(&self) -> f64 {
if self.degrees() <= Self::half_turn() {
self.degrees()
} else {
self.degrees() - Self::BASE
}
}
#[deprecated(since="0.2.3", note="please use `to_gis()` instead")]
pub fn to_180(&self) -> f64 {
self.to_gis()
}
pub fn rotations(&self) -> i64 {
(self.0 / Self::BASE).floor() as i64
}
#[deprecated(since="0.1.0", note="please use `rotations()` instead")]
pub fn turns(&self) -> i64 {
self.rotations()
}
pub fn value(&self) -> f64 {
self.0
}
pub fn half_turn() -> f64 {
Self::BASE / 2.0
}
pub fn as_tuple(&self) -> (f64, i64) {
(self.to_f64(), self.rotations())
}
pub fn multiply(mut self, multiple: f64) -> Self {
self.0 *= multiple;
self
}
pub fn divide(mut self, divisor: f64) -> Self {
self.0 /= divisor;
self
}
pub fn angle_f64(&self, other_value: f64) -> f64 {
let diff = (other_value % Self::BASE) - self.degrees();
if diff.abs() <= Self::half_turn() {
diff
} else {
let alt_val = (Self::BASE + diff) % Self::BASE;
if alt_val < Self::half_turn() {
alt_val
} else {
alt_val - Self::BASE
}
}
}
pub fn angle(&self, other_value: Ring360) -> f64 {
self.angle_f64(other_value.to_f64())
}
}
impl Add for Ring360 {
type Output = Ring360;
fn add(mut self, other: Ring360) -> Self {
self.0 += other.value();
self
}
}
impl Sub for Ring360 {
type Output = Ring360;
fn sub(mut self, other: Ring360) -> Self {
self.0 -= other.value();
self
}
}
impl fmt::Display for Ring360 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.degrees())
}
}
pub trait ToRing360 {
fn to_360(&self) -> Ring360;
fn to_360_gis(&self) -> Ring360;
fn mod_360(&self) -> Self;
fn angle_360(&self, other_value: f64) -> Self;
}
impl ToRing360 for f64 {
fn to_360(&self) -> Ring360 {
Ring360(*self)
}
fn to_360_gis(&self) -> Ring360 {
Ring360::from_gis(*self)
}
fn mod_360(&self) -> f64 {
Ring360(*self).to_f64()
}
fn angle_360(&self, other_value: f64) -> f64 {
Ring360(*self).angle_f64(other_value)
}
}