Skip to content

Commit

Permalink
Merge pull request #37 from DavJCosby/new-api
Browse files Browse the repository at this point in the history
Mutable filters
  • Loading branch information
DavJCosby authored Dec 18, 2023
2 parents 3192e43 + 8818492 commit c7a693a
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 91 deletions.
14 changes: 14 additions & 0 deletions sled/src/led.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,17 @@ impl Led {
self.segment
}
}

impl PartialEq for Led {
fn eq(&self, other: &Self) -> bool {
self.index() == other.index()
}
}

impl Eq for Led {}

impl std::hash::Hash for Led {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.index.hash(state);
}
}
1 change: 1 addition & 0 deletions sled/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub use error::SledError;
pub use glam::Vec2;
pub use led::Led;
pub use sled::Sled;
pub use sled::CollectionOfLeds;

/// Exposes [palette](https://crates.io/crates/palette)'s color management tools and brings the Rgb struct forward so as to be easier to import/qualify in Sled projects.
pub mod color {
Expand Down
268 changes: 177 additions & 91 deletions sled/src/sled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use crate::{
Vec2,
};

use std::ops::{Index, IndexMut};
use std::{
collections::HashSet,
ops::{Index, IndexMut},
};
use std::{ops::Range, usize};

#[allow(dead_code)]
Expand Down Expand Up @@ -834,41 +837,41 @@ impl Sled {
return self.leds.iter().filter(|led| filter(led)).collect();
}

pub fn filter_mut(&mut self, filter: impl Fn(&Led) -> bool) -> Vec<&mut Led> {
return self.leds.iter_mut().filter(|led| filter(led)).collect();
}
// pub fn filter_mut(&mut self, filter: impl Fn(&Led) -> bool) -> Vec<&mut Led> {
// return self.leds.iter_mut().filter(|led| filter(led)).collect();
// }

pub fn filter_by_angle(&self, angle_filter: impl Fn(f32) -> bool) -> Vec<&Led> {
self.filter(|led| angle_filter(led.angle()))
}

pub fn filter_by_angle_mut(&mut self, angle_filter: impl Fn(f32) -> bool) -> Vec<&mut Led> {
self.filter_mut(|led| angle_filter(led.angle()))
}
// pub fn filter_by_angle_mut(&mut self, angle_filter: impl Fn(f32) -> bool) -> Vec<&mut Led> {
// self.filter_mut(|led| angle_filter(led.angle()))
// }

pub fn filter_by_dir(&self, dir_filter: impl Fn(Vec2) -> bool) -> Vec<&Led> {
self.filter(|led| dir_filter(led.direction()))
}

pub fn filter_by_dir_mut(&mut self, dir_filter: impl Fn(Vec2) -> bool) -> Vec<&mut Led> {
self.filter_mut(|led| dir_filter(led.direction()))
}
// pub fn filter_by_dir_mut(&mut self, dir_filter: impl Fn(Vec2) -> bool) -> Vec<&mut Led> {
// self.filter_mut(|led| dir_filter(led.direction()))
// }

pub fn filter_by_pos(&self, pos_filter: impl Fn(Vec2) -> bool) -> Vec<&Led> {
self.filter(|led| pos_filter(led.position()))
}

pub fn filter_by_pos_mut(&mut self, pos_filter: impl Fn(Vec2) -> bool) -> Vec<&mut Led> {
self.filter_mut(|led| pos_filter(led.position()))
}
// pub fn filter_by_pos_mut(&mut self, pos_filter: impl Fn(Vec2) -> bool) -> Vec<&mut Led> {
// self.filter_mut(|led| pos_filter(led.position()))
// }

pub fn filter_by_dist(&self, dist_filter: impl Fn(f32) -> bool) -> Vec<&Led> {
self.filter(|led| dist_filter(led.distance()))
}

pub fn filter_by_dist_mut(&mut self, dist_filter: impl Fn(f32) -> bool) -> Vec<&mut Led> {
self.filter_mut(|led| dist_filter(led.distance()))
}
// pub fn filter_by_dist_mut(&mut self, dist_filter: impl Fn(f32) -> bool) -> Vec<&mut Led> {
// self.filter_mut(|led| dist_filter(led.distance()))
// }

pub fn filter_by_dist_from(&self, pos: Vec2, dist_filter: impl Fn(f32) -> bool) -> Vec<&Led> {
self.filter(|led| {
Expand All @@ -877,16 +880,16 @@ impl Sled {
})
}

pub fn filter_by_dist_from_mut(
&mut self,
pos: Vec2,
dist_filter: impl Fn(f32) -> bool,
) -> Vec<&mut Led> {
self.filter_mut(|led| {
let dist = pos.distance(led.position());
dist_filter(dist)
})
}
// pub fn filter_by_dist_from_mut(
// &mut self,
// pos: Vec2,
// dist_filter: impl Fn(f32) -> bool,
// ) -> Vec<&mut Led> {
// self.filter_mut(|led| {
// let dist = pos.distance(led.position());
// dist_filter(dist)
// })
// }
}

/// Maps
Expand Down Expand Up @@ -950,101 +953,184 @@ impl Sled {
}

pub trait CollectionOfLeds {
// Some methods that might make sense:
// - get_closest_to(), get_furthest_from()
// - filter() for chaining
// - etc

// Indices, ranges, and some others might not make sense.

fn filter(&self, filter: impl Fn(&Led) -> bool) -> Vec<&Led>;
fn get_closest_to(&self, center_point: Vec2) -> &Led;
}
// syntax sugar for .iter().filter().collect()
fn filter(&self, filter: impl Fn(&Led) -> bool) -> Self;

pub trait CollectionOfLedsMut {
// A lot of normal set methods probably don't make the most sense here. More likely use cases are:
// - set_all()
// - filter_mut() for chaining
// - for_each()
// - mapping methods
// - etc

fn filter(&self, filter: impl Fn(&Led) -> bool) -> Vec<&Led>;

fn set_all(&mut self, color: Rgb);
fn and(&mut self, other: &Self) -> Self;
fn or(&mut self, other: &Self) -> Self;

fn get_closest(&self) -> &Led;
fn get_closest_to(&self, pos: Vec2) -> &Led;
fn get_closest_to_mut(&mut self, pos: Vec2) -> &mut Led;
fn set_closest_to(&mut self, pos: Vec2, color: Rgb);

fn map(&mut self, led_to_color_map: impl Fn(&Led) -> Rgb);
fn get_furthest(&self) -> &Led;
fn get_furthest_from(&self, pos: Vec2) -> &Led;

fn get_within_dist(&self, dist: f32) -> Self;
fn get_within_dist_from(&self, dist: f32, pos: Vec2) -> Self;
}

impl CollectionOfLeds for Vec<&Led> {
fn filter(&self, filter: impl Fn(&Led) -> bool) -> Vec<&Led> {
fn filter(&self, filter: impl Fn(&Led) -> bool) -> Self {
self.iter()
.filter_map(|led| filter(led).then_some(*led))
.collect()
}

fn and(&mut self, other: &Self) -> Self {
// definitely can be optimized
let mut copy = self.clone();
copy.retain(|led| filter(led));
copy.retain(|led| other.contains(led));
copy
}

// regular get_closest should be possible to as each led already stores its distance.
fn or(&mut self, other: &Self) -> Self {
let mut set = HashSet::new();
self.iter().for_each(|led| {
set.insert(*led);
});

fn get_closest_to(&self, pos: Vec2) -> &Led {
self.iter()
.min_by(|l, r| {
let d1 = l.position().distance_squared(pos);
let d2 = r.position().distance_squared(pos);
d1.partial_cmp(&d2).unwrap()
})
.unwrap()
other.iter().for_each(|led| {
set.insert(*led);
});

set.iter().map(|led| *led).collect()
}
}

impl CollectionOfLedsMut for Vec<&mut Led> {
fn filter(&self, filter: impl Fn(&Led) -> bool) -> Vec<&Led> {
let mut copy: Vec<&Led> = self.iter().map(|led| &**led).collect();
copy.retain(|led| filter(led));
copy
fn get_closest(&self) -> &Led {
self.iter()
.min_by(|a, b| a.distance().partial_cmp(&b.distance()).unwrap())
.unwrap()
}

fn get_closest_to(&self, pos: Vec2) -> &Led {
self.iter()
.min_by(|l, r| {
let d1 = l.position().distance_squared(pos);
let d2 = r.position().distance_squared(pos);
d1.partial_cmp(&d2).unwrap()
.min_by(|a, b| {
let da = a.position().distance_squared(pos);
let db = b.position().distance_squared(pos);
da.partial_cmp(&db).unwrap()
})
.unwrap()
}

fn get_closest_to_mut(&mut self, pos: Vec2) -> &mut Led {
self.iter_mut()
.min_by(|l, r| {
let d1 = l.position().distance_squared(pos);
let d2 = r.position().distance_squared(pos);
d1.partial_cmp(&d2).unwrap()
})
fn get_furthest(&self) -> &Led {
self.iter()
.max_by(|a, b| a.distance().partial_cmp(&b.distance()).unwrap())
.unwrap()
}

fn set_closest_to(&mut self, pos: Vec2, color: Rgb) {
self.iter_mut()
.min_by(|l, r| {
let d1 = l.position().distance_squared(pos);
let d2 = r.position().distance_squared(pos);
d1.partial_cmp(&d2).unwrap()
fn get_furthest_from(&self, pos: Vec2) -> &Led {
self.iter()
.max_by(|a, b| {
let da = a.position().distance_squared(pos);
let db = b.position().distance_squared(pos);
da.partial_cmp(&db).unwrap()
})
.unwrap()
.color = color;
}

fn set_all(&mut self, color: Rgb) {
for led in self {
led.color = color;
}
fn get_within_dist(&self, dist: f32) -> Self {
self.filter(|led| led.distance() < dist)
}

fn map(&mut self, _led_to_color_map: impl Fn(&Led) -> Rgb) {
todo!()
fn get_within_dist_from(&self, dist: f32, pos: Vec2) -> Self {
let dist_sq = dist.powi(2);
self.filter(|led| led.position().distance_squared(pos) < dist_sq)
}
}

// pub trait CollectionOfLedsMut {
// /// consumes other and modifies itself
// fn and(&mut self, other: Self);
// /// consumes other and modifies itself
// fn or(&mut self, other: Self);

// fn get_closest(&self) -> &Led;
// fn get_closest_to(&self, pos: Vec2) -> &Led;
// fn set_closest(&mut self, color: Rgb);
// fn set_closest_to(&mut self, pos: Vec2, color: Rgb);
// fn modulate_closest(&mut self, color_rule: )

// fn get_furthest(&self) -> &Led;
// fn get_furthest_from(&self, pos: Vec2) -> &Led;

// fn get_within_dist(&self, dist: f32) -> Self;
// fn get_within_dist_from(&self, dist: f32, pos: Vec2) -> Self;

// fn set_all(&mut self, color: Rgb);
// fn set_closest_to(&mut self, pos: Vec2, color: Rgb);

// fn map(&mut self, led_to_color_map: impl Fn(&Led) -> Rgb);
// }

// impl CollectionOfLedsMut for Vec<&mut Led> {
// fn and(&mut self, other: Self) {
// self.retain(|led| other.contains(led));
// }

// fn or(&mut self, other: Self) {
// for led in other {
// if !self.contains(&led) {
// self.push(led);
// }
// }
// }

// fn get_closest(&self) -> &Led {
// self.iter()
// .min_by(|a, b| a.distance().partial_cmp(&b.distance()).unwrap())
// .unwrap()
// }

// fn get_closest_to(&self, pos: Vec2) -> &Led {
// self.iter()
// .min_by(|a, b| {
// let da = a.position().distance_squared(pos);
// let db = b.position().distance_squared(pos);
// da.partial_cmp(&db).unwrap()
// })
// .unwrap()
// }

// fn get_furthest(&self) -> &Led {
// self.iter()
// .max_by(|a, b| a.distance().partial_cmp(&b.distance()).unwrap())
// .unwrap()
// }

// fn get_furthest_from(&self, pos: Vec2) -> &Led {
// self.iter()
// .max_by(|a, b| {
// let da = a.position().distance_squared(pos);
// let db = b.position().distance_squared(pos);
// da.partial_cmp(&db).unwrap()
// })
// .unwrap()
// }

// fn get_within_dist(&self, dist: f32) -> Self {
// self.iter()
// .filter_map(|led| (led.distance() < dist).then_some(*led))
// .collect()
// }

// fn get_within_dist_from(&self, dist: f32, pos: Vec2) -> Self {
// let dist_sq = dist.powi(2);
// self.iter()
// .filter_map(|led| (led.position().distance_squared(pos) < dist_sq).then_some(*led))
// .collect()
// }

// fn set_all(&mut self, color: Rgb) {
// for led in self {
// led.color = color;
// }
// }

// fn set_closest_to(&mut self, pos: Vec2, color: Rgb) {
// todo!()
// }

// fn map(&mut self, led_to_color_map: impl Fn(&Led) -> Rgb) {
// todo!()
// }
// }

0 comments on commit c7a693a

Please sign in to comment.