Skip to main content

a5/coordinate_systems/
base.rs

1// A5
2// SPDX-License-Identifier: Apache-2.0
3// Copyright (c) A5 contributors
4
5//! Base types for coordinate systems.
6//!
7//! This module provides fundamental angle types ([`Degrees`] and [`Radians`])
8//! used throughout the coordinate system implementations.
9
10/// Angle measurement in degrees.
11///
12/// This type provides safe handling of degree values with appropriate
13/// normalization for longitude and latitude coordinates.
14#[derive(Debug, PartialEq, Copy, Clone, Default)]
15pub struct Degrees(pub f64);
16
17impl Degrees {
18    pub const fn new_unchecked(value: f64) -> Self {
19        Degrees(value)
20    }
21
22    /// Create new Degrees without any normalization
23    pub fn new(value: f64) -> Self {
24        Degrees(value)
25    }
26
27    /// Get the raw value in degrees
28    pub const fn get(&self) -> f64 {
29        self.0
30    }
31
32    /// Convert to radians
33    pub fn to_radians(self) -> Radians {
34        Radians::new_unchecked(self.0.to_radians())
35    }
36}
37
38impl From<f64> for Degrees {
39    fn from(value: f64) -> Self {
40        Self::new(value)
41    }
42}
43
44impl From<Degrees> for f64 {
45    fn from(degrees: Degrees) -> Self {
46        degrees.get()
47    }
48}
49
50/// Angle measurement in radians.
51///
52/// This type provides safe handling of radian values commonly used
53/// in mathematical calculations and coordinate transformations.
54#[derive(Debug, PartialEq, Copy, Clone, Default)]
55pub struct Radians(pub f64);
56
57impl Radians {
58    pub const fn new_unchecked(value: f64) -> Self {
59        Radians(value)
60    }
61
62    /// Create new Radians with normalization to [0, 2π] range
63    pub fn new(value: f64) -> Self {
64        use std::f64::consts::TAU; // 2π
65        let normalized = value % TAU;
66        Radians(if normalized < 0.0 {
67            normalized + TAU
68        } else {
69            normalized
70        })
71    }
72
73    /// Get the raw value in radians
74    pub const fn get(&self) -> f64 {
75        self.0
76    }
77
78    /// Convert to degrees
79    pub fn to_degrees(self) -> Degrees {
80        Degrees::new_unchecked(self.0.to_degrees())
81    }
82}
83
84impl From<f64> for Radians {
85    fn from(value: f64) -> Self {
86        Self::new(value)
87    }
88}
89
90impl From<Radians> for f64 {
91    fn from(radians: Radians) -> Self {
92        radians.get()
93    }
94}