From bdc41a3145c8cc9afe8afa853b3ee4f3e3d1aa5f Mon Sep 17 00:00:00 2001 From: David Cosby Date: Thu, 28 Mar 2024 14:55:00 -0600 Subject: [PATCH] changed whether results, options, or bools are returned for various methods. See #75 --- examples/calibration.rs | 8 ++-- examples/drivers/comet.rs | 4 +- src/lib.rs | 5 ++- src/sled/directional.rs | 77 ++++++++++++++++++++------------------ src/sled/indexical.rs | 25 +++++++++---- src/sled/meta.rs | 16 ++++---- src/sled/positional.rs | 78 +++++++++++++++++++-------------------- src/sled/segmental.rs | 8 ++++ 8 files changed, 123 insertions(+), 98 deletions(-) diff --git a/examples/calibration.rs b/examples/calibration.rs index fcbfbc0..f114860 100644 --- a/examples/calibration.rs +++ b/examples/calibration.rs @@ -12,10 +12,10 @@ fn main() -> Result<(), SledError> { sled.set_all(Rgb::new(0.1, 0.1, 0.1)); sled.set_vertices(Rgb::new(0.75, 0.75, 0.75)); - sled.set_at_dir(Vec2::new(1.0, 0.0), Rgb::new(1.0, 0.0, 0.0))?; - sled.set_at_dir(Vec2::new(-1.0, 0.0), Rgb::new(0.5, 0.0, 0.0))?; - sled.set_at_dir(Vec2::new(0.0, 1.0), Rgb::new(0.0, 1.0, 0.0))?; - sled.set_at_dir(Vec2::new(0.0, -1.0), Rgb::new(0.0, 0.5, 0.0))?; + sled.set_at_dir(Vec2::new(1.0, 0.0), Rgb::new(1.0, 0.0, 0.0)); + sled.set_at_dir(Vec2::new(-1.0, 0.0), Rgb::new(0.5, 0.0, 0.0)); + sled.set_at_dir(Vec2::new(0.0, 1.0), Rgb::new(0.0, 1.0, 0.0)); + sled.set_at_dir(Vec2::new(0.0, -1.0), Rgb::new(0.0, 0.5, 0.0)); display.set_leds(sled.colors_and_positions_coerced()); display.refresh().unwrap(); diff --git a/examples/drivers/comet.rs b/examples/drivers/comet.rs index 9cee101..009dba0 100644 --- a/examples/drivers/comet.rs +++ b/examples/drivers/comet.rs @@ -35,13 +35,13 @@ fn draw( // speckle in swirling green points for i in 0..GREEN_COUNT { let angle = inner_time_scale + (TAU / GREEN_COUNT as f32) * i as f32 % TAU; - sled.modulate_at_angle(angle, |led| led.color + GREEN)? + sled.modulate_at_angle(angle, |led| led.color + GREEN); } // speckle in swirling blue points for i in 0..BLUE_COUNT { let angle = outer_time_scale + (TAU / BLUE_COUNT as f32) * i as f32 % TAU; - sled.modulate_at_angle(angle, |led| led.color + BLUE)? + sled.modulate_at_angle(angle, |led| led.color + BLUE); } // brighten or darken points depending on time and angle to simulate a sweeping diff --git a/src/lib.rs b/src/lib.rs index 63ecf7e..4866a98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,7 @@ //! [[line_segment]] //! start = [2.0, 2] //! end = [-2.0, 2] +//! //! [[line_segment]] //! start = [-2.0, 2] //! end = [-2.0, 0.0] @@ -68,7 +69,7 @@ //! # use sled::{Sled, color::Rgb}; //! # fn main() -> Result<(), sled::SledError> { //! # let mut sled = Sled::new("./examples/resources/config.toml").unwrap(); -//! sled.set_at_dist(2.0, Rgb::new(1.0, 0.0, 0.0))?; +//! sled.set_at_dist(2.0, Rgb::new(1.0, 0.0, 0.0)); //! # Ok(()) //! # } //! ``` @@ -165,7 +166,7 @@ //! for i in 0..num_colors { //! let alpha = i as f32 / num_colors as f32; //! let angle = elapsed + (std::f32::consts::TAU * alpha); -//! sled.set_at_angle(angle, colors[i])?; +//! sled.set_at_angle(angle, colors[i]); //! } //! //! Ok(()) diff --git a/src/sled/directional.rs b/src/sled/directional.rs index 4f5f03f..a553e42 100644 --- a/src/sled/directional.rs +++ b/src/sled/directional.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use crate::{color::Rgb, error::SledError, led::Led, Filter, Sled}; +use crate::{color::Rgb, led::Led, Filter, Sled}; use glam::Vec2; use smallvec::SmallVec; @@ -26,6 +26,8 @@ impl Sled { /// Returns A [Filter] containing each [LED](Led) in the given direction from the center point. /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// + /// If no LEDs exist at the given direction, the Filter will be empty. + /// /// O(SEGMENTS) pub fn at_dir(&self, dir: Vec2) -> Filter { self.at_dir_from(dir, self.center_point) @@ -33,6 +35,8 @@ impl Sled { /// Returns A [Filter] containing each [LED](Led) in the given direction from a given point. /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. + /// + /// Currently returns no more than 4 LEDs, may change in the future. pub fn at_dir_from(&self, dir: Vec2, pos: Vec2) -> Filter { let intersecting_indices = self.raycast_for_indices(pos, dir); intersecting_indices @@ -45,7 +49,7 @@ impl Sled { /// Modulates the color of each [LED](Led) in the given direction from the center point. /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// - /// Returns an [error](SledError) if there is no LED in that direction. + /// Returns false if there is no LED in that direction, true otherwise. /// /// O(SEGMENTS) /// @@ -53,22 +57,18 @@ impl Sled { ///# use sled::{Sled, SledError, color::Rgb, Vec2}; ///# fn demo() -> Result<(), SledError> { ///# let mut sled = Sled::new("./examples/resources/config.toml")?; - /// sled.modulate_at_dir(Vec2::new(0.0, 1.0), |led| led.color * 2.0)?; + /// sled.modulate_at_dir(Vec2::new(0.0, 1.0), |led| led.color * 2.0); ///# Ok(()) ///# } /// ``` - pub fn modulate_at_dir Rgb>( - &mut self, - dir: Vec2, - color_rule: F, - ) -> Result<(), SledError> { + pub fn modulate_at_dir Rgb>(&mut self, dir: Vec2, color_rule: F) -> bool { self.modulate_at_dir_from(dir, self.center_point, color_rule) } /// Modulates the color of each [LED](Led) in the given direction from a given point. /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// - /// Returns an [error](SledError) if there is no LED in that direction. + /// Returns false if there is no LED in that direction, true otherwise. /// /// O(SEGMENTS) /// @@ -80,7 +80,7 @@ impl Sled { /// let from = Vec2::new(0.25, -0.6); /// sled.modulate_at_dir_from(dir, from, |led| { /// led.color * 2.0 - /// })?; + /// }); ///# Ok(()) ///# } /// ``` @@ -89,47 +89,49 @@ impl Sled { dir: Vec2, pos: Vec2, color_rule: F, - ) -> Result<(), SledError> { + ) -> bool { let intersecting_indices = self.raycast_for_indices(pos, dir); if intersecting_indices.is_empty() { - return SledError::new(format!("No LED in directon: {} from {}", dir, pos)).as_err(); + return false; } for index in intersecting_indices { let led = &mut self.leds[index]; led.color = color_rule(led); } - Ok(()) + + true } /// Sets the color of each [LED](Led) in the given direction from the center. /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// - /// Returns an [error](SledError) if there is no LED in that direction. + /// Returns false if there is no LED in that direction, true otherwise. /// /// O(SEGMENTS) - pub fn set_at_dir(&mut self, dir: Vec2, color: Rgb) -> Result<(), SledError> { + pub fn set_at_dir(&mut self, dir: Vec2, color: Rgb) -> bool { self.set_at_dir_from(dir, self.center_point, color) } /// Sets the color of each [LED](Led) in the given direction from a given point. /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// - /// Returns an [error](SledError) if there is no LED in that direction. + /// Returns false if there is no LED in that direction, true otherwise. /// /// O(SEGMENTS) - pub fn set_at_dir_from(&mut self, dir: Vec2, pos: Vec2, color: Rgb) -> Result<(), SledError> { + pub fn set_at_dir_from(&mut self, dir: Vec2, pos: Vec2, color: Rgb) -> bool { let intersecting_indices = self.raycast_for_indices(pos, dir); if intersecting_indices.is_empty() { - return SledError::new(format!("No LED in directon: {} from {}", dir, pos)).as_err(); + return false; } for index in intersecting_indices { self.leds[index].color = color; } - Ok(()) + + true } /* angle setters/getters */ @@ -140,6 +142,10 @@ impl Sled { /// /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// + /// If no LEDs exist at the given direction, the Filter will be empty. + /// + /// Currently returns no more than 4 LEDs, may change in the future. + /// /// O(SEGMENTS) pub fn at_angle(&self, angle: f32) -> Filter { let dir = Vec2::from_angle(angle); @@ -152,6 +158,10 @@ impl Sled { /// /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// + /// If no LEDs exist at the given direction, the Filter will be empty. + /// + /// Currently returns no more than 4 LEDs, may change in the future. + /// /// O(SEGMENTS) pub fn at_angle_from(&self, angle: f32, pos: Vec2) -> Filter { let dir = Vec2::from_angle(angle); @@ -164,7 +174,7 @@ impl Sled { /// /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// - /// Returns an [error](SledError) if there is no LED in that direction. + /// Returns false if there is no LED at that angle, true otherwise. /// /// O(SEGMENTS) /// @@ -173,15 +183,11 @@ impl Sled { /// use std::f32::consts::PI; ///# fn demo() -> Result<(), SledError> { ///# let mut sled = Sled::new("./examples/resources/config.toml")?; - /// sled.modulate_at_angle(PI / 4.0, |led| led.color * 2.0)?; + /// sled.modulate_at_angle(PI / 4.0, |led| led.color * 2.0); ///# Ok(()) ///# } /// ``` - pub fn modulate_at_angle Rgb>( - &mut self, - angle: f32, - color_rule: F, - ) -> Result<(), SledError> { + pub fn modulate_at_angle Rgb>(&mut self, angle: f32, color_rule: F) -> bool { self.modulate_at_angle_from(angle, self.center_point, color_rule) } @@ -191,7 +197,7 @@ impl Sled { /// /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// - /// Returns an [error](SledError) if there is no LED in that direction. + /// Returns false if there is no LED at that angle, true otherwise. /// /// O(SEGMENTS) /// @@ -202,7 +208,7 @@ impl Sled { ///# let mut sled = Sled::new("./examples/resources/config.toml")?; /// let angle = PI * 1.25; /// let from = Vec2::new(0.3, 0.2); - /// sled.modulate_at_angle_from(angle, from, |led| led.color * 2.0)?; + /// sled.modulate_at_angle_from(angle, from, |led| led.color * 2.0); ///# Ok(()) ///# } /// ``` @@ -211,7 +217,7 @@ impl Sled { angle: f32, pos: Vec2, color_rule: F, - ) -> Result<(), SledError> { + ) -> bool { let dir = Vec2::from_angle(angle); self.modulate_at_dir_from(dir, pos, color_rule) } @@ -221,8 +227,10 @@ impl Sled { /// /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// + /// Returns false if there is no LED at that angle, true otherwise. + /// /// O(SEGMENTS) - pub fn set_at_angle(&mut self, angle: f32, color: Rgb) -> Result<(), SledError> { + pub fn set_at_angle(&mut self, angle: f32, color: Rgb) -> bool { self.set_at_angle_from(angle, self.center_point, color) } @@ -231,13 +239,10 @@ impl Sled { /// /// Calculated by performing a raycast against each line segment and finding the closest LED to the point of contact. /// + /// Returns false if there is no LED at that angle, true otherwise. + /// /// O(SEGMENTS) - pub fn set_at_angle_from( - &mut self, - angle: f32, - pos: Vec2, - color: Rgb, - ) -> Result<(), SledError> { + pub fn set_at_angle_from(&mut self, angle: f32, pos: Vec2, color: Rgb) -> bool { let dir = Vec2::from_angle(angle); self.set_at_dir_from(dir, pos, color) } diff --git a/src/sled/indexical.rs b/src/sled/indexical.rs index 8e353b1..febcb6c 100644 --- a/src/sled/indexical.rs +++ b/src/sled/indexical.rs @@ -93,17 +93,17 @@ impl Sled { /// # Index and range-based read and write methods impl Sled { - /// Returns a [Filter] containing all [LEDs](Led) with indices within `index_range`. - /// Returns an [error](SledError) if the range extends beyond the size of the system. + /// Returns a Some([Filter]) containing all [LEDs](Led) with indices within `index_range`. + /// Returns None if the range extends beyond the size of the system. /// /// O(RANGE_SIZE) /// - pub fn range(&self, index_range: Range) -> Result { + pub fn range(&self, index_range: Range) -> Option { if index_range.end < self.num_leds { let led_range = &self.leds[index_range]; - Ok(led_range.into()) + Some(led_range.into()) } else { - SledError::new("Index range extends beyond size of system.".to_string()).as_err() + None } } @@ -155,6 +155,8 @@ impl Sled { } /// For-each method granting mutable access to each [LED](Led) with an index in `index_range` + /// + /// Returns an [error](SledError) if the range extends beyond the size of the system. /// /// O(RANGE_SIZE) /// @@ -169,7 +171,16 @@ impl Sled { /// } /// }); /// ``` - pub fn for_each_in_range(&mut self, index_range: Range, func: F) { + pub fn for_each_in_range( + &mut self, + index_range: Range, + func: F, + ) -> Result<(), SledError> { + if index_range.end >= self.num_leds { + return SledError::new("Index range extends beyond size of system.".to_string()) + .as_err(); + } self.leds[index_range].iter_mut().for_each(func); + Ok(()) } -} \ No newline at end of file +} diff --git a/src/sled/meta.rs b/src/sled/meta.rs index 6aa4c31..bcfe2eb 100644 --- a/src/sled/meta.rs +++ b/src/sled/meta.rs @@ -87,7 +87,9 @@ impl Sled { }) } - /// Returns a copy of the system's [LEDs](Led), stored in an ordered vector. + /// Returns a read-only iterator over the system's [LEDs](Led). + /// + /// If you need owned copies of these values, `.collect()` this iterator into a Vector. /// /// O(LEDS) /// @@ -100,11 +102,11 @@ impl Sled { /// ); /// } /// ``` - pub fn leds(&self) -> Vec { - self.leds.clone() + pub fn leds(&self) -> impl Iterator { + self.leds.iter() } - /// Returns an Iterator of the 32-bit RGB colors for each [LED](Led) in the system + /// Returns an Iterator over the 32-bit RGB colors for each [LED](Led) in the system /// /// O(LEDS) /// @@ -122,7 +124,7 @@ impl Sled { self.leds.iter().map(|led| led.color) } - /// Returns an Iterator of the RGB colors for each [LED](Led) in the system. + /// Returns an Iterator over the RGB colors for each [LED](Led) in the system. /// Type annotations allow you to coerce from 32-bit RGB into another depth. /// /// O(LEDS) @@ -144,7 +146,7 @@ impl Sled { self.leds.iter().map(|led| led.color.into_format::()) } - /// Returns an Iterator of Vec2s, representing the position of each [LED](Led) in the system. + /// Returns an Iterator over Vec2s, representing the position of each [LED](Led) in the system. /// /// O(LEDS) pub fn positions(&self) -> impl Iterator + '_ { @@ -162,7 +164,7 @@ impl Sled { /// Supports color coercion just like [Sled::colors_coerced()](colors_coerced()) /// /// O(LEDS) - /// + /// /// ```rust /// # use sled::{Sled, color::Rgb}; ///# let sled = Sled::new("./examples/resources/config.toml").unwrap(); diff --git a/src/sled/positional.rs b/src/sled/positional.rs index 3752461..1899c63 100644 --- a/src/sled/positional.rs +++ b/src/sled/positional.rs @@ -2,7 +2,6 @@ use std::collections::HashSet; use crate::{ color::Rgb, - error::SledError, led::Led, sled::{Filter, Sled}, }; @@ -15,9 +14,9 @@ impl Sled { /* closest getters/setters */ /// Returns the index of the [LED](Led) closest to a given point. - /// + /// /// O(SEGMENTS) - /// + /// pub fn index_of_closest_to(&self, pos: Vec2) -> usize { // get the closest point on each segment and bundle relevant info, @@ -38,14 +37,14 @@ impl Sled { } /// Returns the [LED](Led) closest to the center point. - /// + /// /// O(1) pub fn closest(&self) -> &Led { &self.leds[self.index_of_closest] } /// Returns the [LED](Led) closest to a given point. - /// + /// /// O(SEGMENTS) pub fn closest_to(&self, pos: Vec2) -> &Led { let index_of_closest = self.index_of_closest_to(pos); @@ -105,7 +104,7 @@ impl Sled { /* furthest getters/setters */ /// Returns the index of the [LED](Led) furthest from a given point. - /// + /// /// O(VERTICES) pub fn index_of_furthest_from(&self, pos: Vec2) -> usize { // get the distance_squared of each vertex point, then find out which is the furthest. @@ -123,20 +122,20 @@ impl Sled { } /// Returns the index of the [LED](Led) furthest from the center point. - /// + /// /// O(1) pub fn index_of_furthest(&self) -> usize { self.index_of_furthest } /// Returns the [LED](Led) furthest from the center point. - /// + /// /// O(1) pub fn furthest(&self) -> &Led { &self.leds[self.index_of_furthest] } /// Returns the [LED](Led) furthest from a given point. - /// + /// /// O(VERTICES) pub fn furthest_from(&self, pos: Vec2) -> &Led { let index_of_furthest = self.index_of_furthest_from(pos); @@ -223,11 +222,7 @@ impl Sled { all_at_distance.into() } - pub fn modulate_at_dist Rgb>( - &mut self, - dist: f32, - color_rule: F, - ) -> Result<(), SledError> { + pub fn modulate_at_dist Rgb>(&mut self, dist: f32, color_rule: F) -> bool { self.modulate_at_dist_from(dist, self.center_point, color_rule) } @@ -236,45 +231,30 @@ impl Sled { dist: f32, pos: Vec2, color_rule: F, - ) -> Result<(), SledError> { + ) -> bool { let indices = self.indices_at_dist(pos, dist); - - if indices.is_empty() { - return SledError::new(format!( - "No LEDs exist at a distance of {} from {}", - dist, pos - )) - .as_err(); - } - + let anything_found = !indices.is_empty(); for i in indices { let led = &mut self.leds[i]; led.color = color_rule(led); } - Ok(()) + return anything_found; } - pub fn set_at_dist(&mut self, dist: f32, color: Rgb) -> Result<(), SledError> { + pub fn set_at_dist(&mut self, dist: f32, color: Rgb) -> bool { self.set_at_dist_from(dist, self.center_point, color) } - pub fn set_at_dist_from(&mut self, dist: f32, pos: Vec2, color: Rgb) -> Result<(), SledError> { + pub fn set_at_dist_from(&mut self, dist: f32, pos: Vec2, color: Rgb) -> bool { let indices = self.indices_at_dist(pos, dist); - - if indices.is_empty() { - return SledError::new(format!( - "No LEDs exist at a distance of {} from the center point.", - dist - )) - .as_err(); - } + let anything_found = !indices.is_empty(); for index in indices { self.leds[index].color = color; } - Ok(()) + return anything_found; } /* within distance methods */ @@ -297,20 +277,30 @@ impl Sled { all_within_distance.into() } - pub fn modulate_within_dist Rgb>(&mut self, dist: f32, color_rule: F) { + pub fn modulate_within_dist Rgb>(&mut self, dist: f32, color_rule: F) -> bool { + let mut changes_made = false; + for led in &mut self.leds { if led.distance() < dist { led.color = color_rule(led); + changes_made = true; } } + + changes_made } - pub fn set_within_dist(&mut self, dist: f32, color: Rgb) { + pub fn set_within_dist(&mut self, dist: f32, color: Rgb) -> bool { + let mut changes_made = false; + for led in &mut self.leds { if led.distance() < dist { led.color = color; + changes_made = true; } } + + changes_made } pub fn modulate_within_dist_from Rgb>( @@ -318,23 +308,31 @@ impl Sled { dist: f32, pos: Vec2, color_rule: F, - ) { + ) -> bool { let target_sq = dist.powi(2); + let mut changes_made = false; for led in &mut self.leds { if led.position().distance_squared(pos) < target_sq { led.color = color_rule(led); + changes_made = true } } + + changes_made } - pub fn set_within_dist_from(&mut self, dist: f32, pos: Vec2, color: Rgb) { + pub fn set_within_dist_from(&mut self, dist: f32, pos: Vec2, color: Rgb) -> bool { let target_sq = dist.powi(2); + let mut changes_made = false; for led in &mut self.leds { if led.position().distance_squared(pos) < target_sq { led.color = color; + changes_made = true; } } + + changes_made } } diff --git a/src/sled/segmental.rs b/src/sled/segmental.rs index 6f47afd..3aac91e 100644 --- a/src/sled/segmental.rs +++ b/src/sled/segmental.rs @@ -66,6 +66,8 @@ impl Sled { } /// Returns the set of all [LEDs](Led) assigned to the line segments whose indices are within the given range. + /// + /// If the range exceeds the number of segments in the system, returns None. /// /// O(LEDS_IN_SEGMENTS) /// @@ -146,6 +148,8 @@ impl Sled { /// For-each method granting mutable access to each [LED](Led) assigned to the line segment with index `segment_index`. /// Also passes an "alpha" value into the closure, representing how far along the line segment you are. 0 = first LED in segement, 1 = last. /// + /// Returns an [error](SledError) if the no segment of given index exists. + /// /// O(LEDS_IN_SEGMENT) /// /// ```rust @@ -196,6 +200,8 @@ impl Sled { /// Modulates the color of the [LED](Led) that represents the vertex the given index, if it exists. Returns an [error](SledError) if not. /// Vertices are distinct from line segement endpoints in that line segments with touching endpoints will share a vertex. /// + /// Returns an [error](SledError) if no vertex of given index exists. + /// /// O(1) /// /// ```rust @@ -225,6 +231,8 @@ impl Sled { /// Sets the color of the [LED](Led) that represents the vertex the given index, if it exists. Returns an [error](SledError) if not. /// Vertices are distinct from line segement endpoints in that line segments with touching endpoints will share a vertex. /// + /// Returns an [error](SledError) if no vertex of given index exists. + /// /// O(1) /// pub fn set_vertex(&mut self, vertex_index: usize, color: Rgb) -> Result<(), SledError> {