smooth_frame/input/frame/
mod.rs1mod path_builder;
2mod validation;
3
4use crate::errors::SmoothError;
5use crate::output::path::SmoothPath;
6use crate::types::Point;
7use crate::utils::clamp01;
8
9use path_builder::build_smooth_frame_path;
10use validation::validate_frame;
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct SmoothFrame {
15 points: Vec<Point>,
16 radius: f64,
17 smoothing: f64,
18}
19
20impl SmoothFrame {
21 #[must_use]
25 pub fn closed(points: impl IntoIterator<Item = Point>) -> Self {
26 Self {
27 points: points.into_iter().collect(),
28 radius: 0.0,
29 smoothing: 0.0,
30 }
31 }
32
33 #[must_use]
35 pub fn with_radius(mut self, radius: f64) -> Self {
36 self.radius = radius;
37 self
38 }
39
40 #[must_use]
42 pub fn with_smoothing(mut self, smoothing: f64) -> Self {
43 self.smoothing = smoothing;
44 self
45 }
46
47 #[must_use]
49 pub fn points(&self) -> &[Point] {
50 &self.points
51 }
52
53 pub fn to_path(&self) -> Result<SmoothPath, SmoothError> {
55 validate_frame(&self.points)?;
56
57 if self.radius < 0.0 {
58 return Err(SmoothError::NegativeInput);
59 }
60 if !self.radius.is_finite() || !self.smoothing.is_finite() {
61 return Err(SmoothError::NonFiniteInput);
62 }
63
64 Ok(build_smooth_frame_path(
65 &self.points,
66 self.radius,
67 clamp01(self.smoothing),
68 ))
69 }
70}