use std::fmt::Debug;
use crate::core::Normal;
#[derive(Debug, Clone)]
pub struct Group {
tier_1_positions: Vec<Normal>,
tier_2_positions: Vec<Normal>,
tier_3_positions: Vec<Normal>,
len: usize,
hashed: u64,
}
impl Default for Group {
fn default() -> Self {
Group::center(Tier::One)
}
}
impl Group {
pub fn from_normalized(tick_marks: &[(Normal, Tier)]) -> Self {
use std::hash::{Hash, Hasher};
let mut hasher = iced_native::Hasher::default();
tick_marks.len().hash(&mut hasher);
let len = tick_marks.len();
let mut tier_1_positions: Vec<Normal> = Vec::new();
let mut tier_2_positions: Vec<Normal> = Vec::new();
let mut tier_3_positions: Vec<Normal> = Vec::new();
for tick_mark in tick_marks.iter() {
tick_mark.1.hash(&mut hasher);
((tick_mark.0.as_f32() * 10000000.0) as u64).hash(&mut hasher);
match tick_mark.1 {
Tier::One => {
tier_1_positions.push(tick_mark.0);
}
Tier::Two => {
tier_2_positions.push(tick_mark.0);
}
Tier::Three => {
tier_3_positions.push(tick_mark.0);
}
}
}
Self {
tier_1_positions,
tier_2_positions,
tier_3_positions,
len,
hashed: hasher.finish(),
}
}
pub fn center(tier: Tier) -> Self {
Self::from_normalized(&[(Normal::CENTER, tier)])
}
pub fn min_max(tier: Tier) -> Self {
Self::from_normalized(&[(Normal::MIN, tier), (Normal::MAX, tier)])
}
pub fn min_max_and_center(min_max_tier: Tier, center_tier: Tier) -> Self {
Self::from_normalized(&[
(Normal::MIN, min_max_tier),
(Normal::CENTER, center_tier),
(Normal::MAX, min_max_tier),
])
}
pub fn subdivided(
one: usize,
two: usize,
three: usize,
sides: Option<Tier>,
) -> Self {
let mut tick_marks: Vec<(Normal, Tier)> =
Vec::with_capacity(one + (two * one) + (three * two * one) + 2);
let one_ranges = one + 1;
let two_ranges = two + 1;
let three_ranges = three + 1;
let one_span = 1.0 / one_ranges as f32;
let two_span = one_span / two_ranges as f32;
let three_span = two_span / three_ranges as f32;
for i_1 in 0..one_ranges {
let one_pos = (i_1 as f32 * one_span) + one_span;
if i_1 != one {
tick_marks.push((Normal::from_clipped(one_pos), Tier::One));
}
for i_2 in 0..two_ranges {
let two_pos = (i_2 as f32 * two_span) + two_span;
if i_2 != two {
tick_marks.push((
Normal::from_clipped(one_pos - two_pos),
Tier::Two,
));
}
for i_3 in 0..three {
let three_pos = (i_3 as f32 * three_span) + three_span;
tick_marks.push((
Normal::from_clipped(one_pos - two_pos + three_pos),
Tier::Three,
));
}
}
}
if let Some(side_tier) = sides {
tick_marks.push((Normal::MIN, side_tier));
tick_marks.push((Normal::MAX, side_tier));
}
Self::from_normalized(&tick_marks)
}
pub fn evenly_spaced(len: usize, tier: Tier) -> Self {
let mut tick_marks: Vec<(Normal, Tier)> = Vec::with_capacity(len);
if len == 1 {
tick_marks.push((Normal::MIN, tier));
} else if len != 0 {
let len_min_1 = len - 1;
let span = 1.0 / len_min_1 as f32;
for i in 0..len_min_1 {
let pos = i as f32 * span;
tick_marks.push((Normal::from_clipped(pos), tier));
}
tick_marks.push((Normal::MAX, tier));
}
Self::from_normalized(&tick_marks)
}
pub fn tier_1(&self) -> Option<&Vec<Normal>> {
if self.tier_1_positions.is_empty() {
None
} else {
Some(&self.tier_1_positions)
}
}
pub fn tier_2(&self) -> Option<&Vec<Normal>> {
if self.tier_2_positions.is_empty() {
None
} else {
Some(&self.tier_2_positions)
}
}
pub fn tier_3(&self) -> Option<&Vec<Normal>> {
if self.tier_3_positions.is_empty() {
None
} else {
Some(&self.tier_3_positions)
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub(crate) fn hashed(&self) -> u64 {
self.hashed
}
}
impl From<Vec<(Normal, Tier)>> for Group {
fn from(vec: Vec<(Normal, Tier)>) -> Self {
Self::from_normalized(&vec)
}
}
impl From<&[(Normal, Tier)]> for Group {
fn from(slice: &[(Normal, Tier)]) -> Self {
Self::from_normalized(slice)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, std::hash::Hash)]
pub enum Tier {
One,
Two,
Three,
}
impl Default for Tier {
fn default() -> Self {
Tier::One
}
}