#[allow(dead_code)]
const HUE_FAMILY_CODES: [(u8, &str); 10] = [
(1, "BG"), (2, "G"), (3, "GY"), (4, "Y"), (5, "YR"),
(6, "R"), (7, "RP"), (8, "P"), (9, "PB"), (10, "B")
];
#[inline]
pub fn hue_to_astm_hue(hue: f64, code: u8) -> f64 {
let raw = (17.0 - code as f64) % 10.0 + (hue * 0.1) - 0.5;
let single_hue = ((raw % 10.0) + 10.0) % 10.0;
linear_interpolate_hue_angle(single_hue)
}
#[inline]
pub fn hue_angle_to_hue(hue_angle: f64) -> (f64, u8) {
let single_hue = reverse_interpolate_hue_angle(hue_angle);
let code = if single_hue <= 0.5 { 7 } else if single_hue <= 1.5 { 6 } else if single_hue <= 2.5 { 5 } else if single_hue <= 3.5 { 4 } else if single_hue <= 4.5 { 3 } else if single_hue <= 5.5 { 2 } else if single_hue <= 6.5 { 1 } else if single_hue <= 7.5 { 10 } else if single_hue <= 8.5 { 9 } else if single_hue <= 9.5 { 8 } else { 7 };
let hue = (10.0 * (single_hue % 1.0) + 5.0) % 10.0;
let final_hue = if hue == 0.0 { 10.0 } else { hue };
(final_hue, code)
}
#[inline]
fn linear_interpolate_hue_angle(single_hue: f64) -> f64 {
let breakpoints = [0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 8.0, 9.0, 10.0];
let angles = [0.0, 45.0, 70.0, 135.0, 160.0, 225.0, 255.0, 315.0, 360.0];
for i in 0..breakpoints.len()-1 {
if single_hue >= breakpoints[i] && single_hue <= breakpoints[i+1] {
let t = (single_hue - breakpoints[i]) / (breakpoints[i+1] - breakpoints[i]);
return angles[i] + t * (angles[i+1] - angles[i]);
}
}
360.0
}
#[inline]
fn reverse_interpolate_hue_angle(hue_angle: f64) -> f64 {
let angles = [0.0, 45.0, 70.0, 135.0, 160.0, 225.0, 255.0, 315.0, 360.0];
let breakpoints = [0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 8.0, 9.0, 10.0];
for i in 0..angles.len()-1 {
if hue_angle >= angles[i] && hue_angle <= angles[i+1] {
let t = (hue_angle - angles[i]) / (angles[i+1] - angles[i]);
return breakpoints[i] + t * (breakpoints[i+1] - breakpoints[i]);
}
}
0.0
}
pub fn bounding_hues_from_renotation(hue: f64, code: u8) -> ((f64, u8), (f64, u8)) {
let mut hue_cw: f64;
let code_cw: u8;
let mut hue_ccw: f64;
let code_ccw: u8;
if (hue % 2.5 - 0.0).abs() < 1e-10 {
if (hue - 0.0).abs() < 1e-10 {
hue_cw = 10.0;
code_cw = increment_code(code);
} else {
hue_cw = hue;
code_cw = code;
}
hue_ccw = hue_cw;
code_ccw = code_cw;
} else {
hue_cw = 2.5 * (hue / 2.5).floor();
hue_ccw = (hue_cw + 2.5) % 10.0;
if (hue_ccw - 0.0).abs() < 1e-10 {
hue_ccw = 10.0;
}
if (hue_cw - 0.0).abs() < 1e-10 {
hue_cw = 10.0;
code_cw = increment_code(code);
} else {
code_cw = code;
}
code_ccw = code;
}
((hue_cw, code_cw), (hue_ccw, code_ccw))
}
fn increment_code(code: u8) -> u8 {
match code {
1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6, 6 => 7, 7 => 8, 8 => 9, 9 => 10, 10 => 1, _ => code }
}
pub fn code_to_family(code: u8) -> &'static str {
match code {
1 => "B",
2 => "BG",
3 => "G",
4 => "GY",
5 => "Y",
6 => "YR",
7 => "R",
8 => "RP",
9 => "P",
10 => "PB",
_ => "N" }
}
#[allow(dead_code)]
pub fn family_to_code(family: &str) -> u8 {
match family {
"B" => 1,
"BG" => 2,
"G" => 3,
"GY" => 4,
"Y" => 5,
"YR" => 6,
"R" => 7,
"RP" => 8,
"P" => 9,
"PB" => 10,
_ => 0 }
}
pub fn hue_to_hue_angle(hue: f64, code: u8) -> f64 {
let single_hue = ((18.0 - code as f64) % 10.0 + (hue / 10.0) - 0.5) % 10.0;
linear_interpolate_hue_angle(single_hue)
}