Skip to content

Commit 4e5bc23

Browse files
committed
Offer both 0 centered and positive hue -> float conversion
1 parent a8317f6 commit 4e5bc23

File tree

5 files changed

+44
-19
lines changed

5 files changed

+44
-19
lines changed

src/hsl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl<T: Float> Mix for Hsl<T> {
7777

7878
fn mix(&self, other: &Hsl<T>, factor: T) -> Hsl<T> {
7979
let factor = clamp(factor, T::zero(), T::one());
80-
let hue_diff: T = (other.hue - self.hue).to_float();
80+
let hue_diff: T = (other.hue - self.hue).to_degrees();
8181

8282
Hsl {
8383
hue: self.hue + factor * hue_diff,

src/hsv.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<T: Float> Mix for Hsv<T> {
7676

7777
fn mix(&self, other: &Hsv<T>, factor: T) -> Hsv<T> {
7878
let factor = clamp(factor, T::zero(), T::one());
79-
let hue_diff: T = (other.hue - self.hue).to_float();
79+
let hue_diff: T = (other.hue - self.hue).to_degrees();
8080

8181
Hsv {
8282
hue: self.hue + factor * hue_diff,

src/hues.rs

+39-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ macro_rules! make_hues {
99
$(#[$doc])+
1010
///
1111
///The hue is a circular type, where `0` and `360` is the same, and
12-
///it's normalized to `(-180, +180]` when it's converted to a linear
12+
///it's normalized to `(-180, 180]` when it's converted to a linear
1313
///number (like `f32`). This makes many calculations easier, but may
1414
///also have some surprising effects if it's expected to act as a
1515
///linear number.
@@ -22,14 +22,24 @@ macro_rules! make_hues {
2222
$name(radians * T::from(180.0).unwrap() / T::from(PI).unwrap())
2323
}
2424

25-
///Convert the hue to radians.
25+
///Get the hue as degrees, in the range `(-180, 180]`.
26+
pub fn to_degrees(self) -> T {
27+
normalize_angle(self.0)
28+
}
29+
30+
///Convert the hue to radians, in the range `(-π, π]`.
2631
pub fn to_radians(self) -> T {
2732
normalize_angle(self.0) * T::from(PI).unwrap() / T::from(180.0).unwrap()
2833
}
2934

30-
///Returns the saved Hue value
31-
pub fn to_float(self) -> T {
32-
normalize_angle(self.0)
35+
///Convert the hue to positive degrees, in the range `[0, 360)`.
36+
pub fn to_positive_degrees(self) -> T {
37+
normalize_angle_positive(self.0)
38+
}
39+
40+
///Convert the hue to positive radians, in the range `[0, 2π)`.
41+
pub fn to_positive_radians(self) -> T {
42+
normalize_angle_positive(self.0) * T::from(PI).unwrap() / T::from(180.0).unwrap()
3343
}
3444
}
3545

@@ -41,13 +51,13 @@ macro_rules! make_hues {
4151

4252
impl Into<f64> for $name<f64> {
4353
fn into(self) -> f64 {
44-
normalize_angle(self.0) as f64
54+
normalize_angle(self.0)
4555
}
4656
}
4757

4858
impl Into<f32> for $name<f32> {
4959
fn into(self) -> f32 {
50-
normalize_angle(self.0) as f32
60+
normalize_angle(self.0)
5161
}
5262
}
5363
impl Into<f32> for $name<f64> {
@@ -58,15 +68,15 @@ macro_rules! make_hues {
5868

5969
impl<T:Float> PartialEq for $name<T> {
6070
fn eq(&self, other: &$name<T>) -> bool {
61-
let hue_s: T = (*self).to_float();
62-
let hue_o: T = (*other).to_float();
71+
let hue_s: T = (*self).to_degrees();
72+
let hue_o: T = (*other).to_degrees();
6373
hue_s.eq(&hue_o)
6474
}
6575
}
6676

6777
impl<T:Float> PartialEq<T> for $name<T> {
6878
fn eq(&self, other: &T) -> bool {
69-
let hue: T = (*self).to_float();
79+
let hue: T = (*self).to_degrees();
7080
hue.eq(&normalize_angle(*other))
7181
}
7282
}
@@ -121,12 +131,27 @@ make_hues! {
121131
}
122132

123133
fn normalize_angle<T: Float>(mut deg: T) -> T {
124-
while deg > T::from(180.0).unwrap() {
125-
deg = deg - T::from(360.0).unwrap();
134+
let c180 = T::from(180.0).unwrap();
135+
let c360 = T::from(360.0).unwrap();
136+
while deg > c180 {
137+
deg = deg - c360;
138+
}
139+
140+
while deg <= -c180 {
141+
deg = deg + c360;
142+
}
143+
144+
deg
145+
}
146+
147+
fn normalize_angle_positive<T: Float>(mut deg: T) -> T {
148+
let c360 = T::from(360.0).unwrap();
149+
while deg >= c360 {
150+
deg = deg - c360;
126151
}
127152

128-
while deg <= -T::from(180.0).unwrap() {
129-
deg = deg + T::from(360.0).unwrap();
153+
while deg < T::zero() {
154+
deg = deg + c360;
130155
}
131156

132157
deg

src/lch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ impl<T: Float> Mix for Lch<T> {
7575

7676
fn mix(&self, other: &Lch<T>, factor: T) -> Lch<T> {
7777
let factor = clamp(factor, T::zero(), T::one());
78-
let hue_diff: T = (other.hue - self.hue).to_float();
78+
let hue_diff: T = (other.hue - self.hue).to_degrees();
7979
Lch {
8080
l: self.l + factor * (other.l - self.l),
8181
chroma: self.chroma + factor * (other.chroma - self.chroma),

src/rgb.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ impl<T: Float> From<Lch<T>> for Rgb<T> {
325325
impl<T: Float> From<Hsv<T>> for Rgb<T> {
326326
fn from(hsv: Hsv<T>) -> Rgb<T> {
327327
let c = hsv.value * hsv.saturation;
328-
let h = ((hsv.hue.to_float() + T::from(360.0).unwrap()) % T::from(360.0).unwrap()) / T::from(60.0).unwrap();
328+
let h = hsv.hue.to_positive_degrees() / T::from(60.0).unwrap();
329329
let x = c * (T::one() - (h % T::from(2.0).unwrap() - T::one()).abs());
330330
let m = hsv.value - c;
331331

@@ -355,7 +355,7 @@ impl<T: Float> From<Hsv<T>> for Rgb<T> {
355355
impl<T: Float> From<Hsl<T>> for Rgb<T> {
356356
fn from(hsl: Hsl<T>) -> Rgb<T> {
357357
let c = (T::one() - (T::from(2.0).unwrap() * hsl.lightness - T::one()).abs()) * hsl.saturation;
358-
let h = ((hsl.hue.to_float() + T::from(360.0).unwrap()) % T::from(360.0).unwrap()) / T::from(60.0).unwrap();
358+
let h = hsl.hue.to_positive_degrees() / T::from(60.0).unwrap();
359359
let x = c * (T::one() - (h % T::from(2.0).unwrap() - T::one()).abs());
360360
let m = hsl.lightness - T::from(0.5).unwrap() * c;
361361

0 commit comments

Comments
 (0)