1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use super::Hex;
impl Hex {
/// Computes squared euclidean distance from `self` to `origin` as an
/// integer number in the Cartesian coordinate system.
/// Euclidean distance can vary for coordinates in the same range, and
/// can be used for operations outside of the hexagonal space, like
/// checking if coordinates are in a circular range instead of an
/// hexagonal range
///
/// Note: For most cases you should use an [`crate::HexLayout`]
///
/// > Source:
/// > Xiangguo Li's 2013 [Paper]. ([DOI]) gives a formula for Euclidean
/// > distance
///
/// [Paper]: https://scholar.google.com/scholar?q=Storage+and+addressing+scheme+for+practical+hexagonal+image+processing
/// [DOI]: https://doi.org/10.1117/1.JEI.22.1.010502
#[must_use]
pub const fn squared_euclidean_length(self) -> i32 {
self.x.pow(2) + self.y.pow(2) + (self.x * self.y)
}
/// Computes euclidean distance from `self` to `origin` as an floating point
/// number in the Cartesian coordinate system.
/// Euclidean distance can vary for coordinates in the same range, and
/// can be used for operations outside of the hexagonal space, like
/// checking if coordinates are in a circular range instead of an
/// hexagonal range
///
/// Note: For most cases you should use an [`crate::HexLayout`]
///
/// > Source:
/// > Xiangguo Li's 2013 [Paper]. ([DOI]) gives a formula for Euclidean
/// > distance
///
/// [Paper]: https://scholar.google.com/scholar?q=Storage+and+addressing+scheme+for+practical+hexagonal+image+processing
/// [DOI]: https://doi.org/10.1117/1.JEI.22.1.010502
#[expect(clippy::cast_precision_loss)]
#[must_use]
pub fn euclidean_length(self) -> f32 {
(self.squared_euclidean_length() as f32).sqrt()
}
/// Computes squared euclidean distance from `self` to `rhs` as an integer
/// number in the Cartesian coordinate system.
/// Euclidean distance can vary for coordinates in the same range, and
/// can be used for operations outside of the hexagonal space, like
/// checking if coordinates are in a circular range instead of an
/// hexagonal range
///
/// Note: For most cases you should use an [`crate::HexLayout`]
///
/// Also check:
/// - [`Hex::euclidean_distance_to`]
/// - [`Hex::circular_range`]
///
/// > Source:
/// > Xiangguo Li's 2013 [Paper]. ([DOI]) gives a formula for Euclidean
/// > distance
///
/// [Paper]: https://scholar.google.com/scholar?q=Storage+and+addressing+scheme+for+practical+hexagonal+image+processing
/// [DOI]: https://doi.org/10.1117/1.JEI.22.1.010502
#[must_use]
pub const fn squared_euclidean_distance_to(self, rhs: Self) -> i32 {
rhs.const_sub(self).squared_euclidean_length()
}
/// Computes euclidean distance from `self` to `rhs` as a floating point
/// number in the Cartesian coordinate system.
/// Euclidean distance can vary for coordinates in the same range, and
/// can be used for operations outside of the hexagonal space, like
/// checking if coordinates are in a circular range instead of an
/// hexagonal range
///
/// Note: For most cases you should use an [`crate::HexLayout`]
///
/// Also check:
/// - [`Hex::squared_euclidean_distance_to`]
/// - [`Hex::circular_range`]
///
/// > Source:
/// > Xiangguo Li's 2013 [Paper]. ([DOI]) gives a formula for Euclidean
/// > distance
///
/// [Paper]: https://scholar.google.com/scholar?q=Storage+and+addressing+scheme+for+practical+hexagonal+image+processing
/// [DOI]: https://doi.org/10.1117/1.JEI.22.1.010502
#[must_use]
#[expect(clippy::cast_precision_loss)]
pub fn euclidean_distance_to(self, rhs: Self) -> f32 {
(self.squared_euclidean_distance_to(rhs) as f32).sqrt()
}
/// Retrieves all [`Hex`] around `self` in a given circular `range`.
///
/// > See also [`Hex::range`] for hexagonal ranges
///
/// Note that this implementation is very naive and inefficient.
/// Use sparingly
///
/// # Example
///
/// ```rust
/// # use hexx::*;
/// let coord = hex(12, 34);
/// assert_eq!(coord.circular_range(0.0).count(), 1);
/// assert_eq!(coord.circular_range(1.0).count(), 7);
/// ```
#[expect(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub fn circular_range(self, range: f32) -> impl Iterator<Item = Self> {
let radius = range.ceil() as u32;
// TODO: Improve this computation to have the smallest hexagon
// which fits the circle
let hex_range = radius + (range / 6.0).floor() as u32;
self.range(hex_range)
.filter(move |h| self.euclidean_distance_to(*h) <= range)
}
}