dms_coordinates/
cardinal.rs1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6#[derive(PartialEq, Eq, Debug, Copy, Clone)]
7#[repr(u16)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub enum Cardinal {
10 North = 0,
12 NorthEast = 45,
14 East = 90,
16 SouthEast = 135,
18 South = 180,
20 SouthWest = 225,
22 West = 270,
24 NorthWest = 315,
26}
27
28impl core::ops::Add<u16> for Cardinal {
29 type Output = Cardinal;
30 fn add(self, rhs: u16) -> Self {
32 Cardinal::from_angle((self.to_angle() + rhs) % 360)
33 }
34}
35
36impl Default for Cardinal {
37 fn default() -> Self {
39 Self::North
40 }
41}
42
43impl core::fmt::Display for Cardinal {
44 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
45 match self {
46 Cardinal::North => write!(f, "N"),
47 Cardinal::NorthEast => write!(f, "NE"),
48 Cardinal::East => write!(f, "E"),
49 Cardinal::SouthEast => write!(f, "SE"),
50 Cardinal::South => write!(f, "S"),
51 Cardinal::SouthWest => write!(f, "SW"),
52 Cardinal::West => write!(f, "W"),
53 Cardinal::NorthWest => write!(f, "NW"),
54 }
55 }
56}
57
58impl Cardinal {
59 pub fn is_latitude(&self) -> bool {
61 match self {
62 Cardinal::North | Cardinal::South => true,
63 _ => false,
64 }
65 }
66 pub fn is_longitude(&self) -> bool {
68 match self {
69 Cardinal::East | Cardinal::West => true,
70 _ => false,
71 }
72 }
73 pub fn same_kind(&self, rhs: Self) -> bool {
76 (self.is_latitude() && rhs.is_latitude()) || (self.is_longitude() && rhs.is_longitude())
77 }
78 pub fn is_northern(&self) -> bool {
80 match self {
81 Cardinal::North | Cardinal::NorthEast | Cardinal::NorthWest => true,
82 _ => false,
83 }
84 }
85 pub fn is_southern(&self) -> bool {
87 match self {
88 Cardinal::South | Cardinal::SouthEast | Cardinal::SouthWest => true,
89 _ => false,
90 }
91 }
92 pub fn is_eastern(&self) -> bool {
94 match self {
95 Cardinal::East | Cardinal::NorthEast | Cardinal::SouthEast => true,
96 _ => false,
97 }
98 }
99 pub fn is_western(&self) -> bool {
101 match self {
102 Cardinal::West | Cardinal::NorthWest | Cardinal::SouthWest => true,
103 _ => false,
104 }
105 }
106 pub fn is_sub_quadrant(&self) -> bool {
108 (self.to_angle() / 45) % 2 > 0
109 }
110 pub fn to_angle(&self) -> u16 {
113 match self {
114 Cardinal::North => 0,
115 Cardinal::NorthEast => 45,
116 Cardinal::East => 90,
117 Cardinal::SouthEast => 135,
118 Cardinal::South => 180,
119 Cardinal::SouthWest => 225,
120 Cardinal::West => 270,
121 Cardinal::NorthWest => 315,
122 }
123 }
124 pub fn from_angle(angle: u16) -> Cardinal {
127 if angle < 45 {
128 Cardinal::North
129 } else if angle < 90 {
130 Cardinal::NorthEast
131 } else if angle < 135 {
132 Cardinal::East
133 } else if angle < 180 {
134 Cardinal::SouthEast
135 } else if angle < 225 {
136 Cardinal::South
137 } else if angle < 270 {
138 Cardinal::SouthWest
139 } else if angle < 315 {
140 Cardinal::West
141 } else {
142 Cardinal::NorthWest
143 }
144 }
145}