anl/
rgba_select.rs

1use super::rgba_module_base::{RgbaModule, RgbaParameter, Rgba};
2use super::implicit_base::ScalarParameter;
3use super::utility::quintic_blend;
4use super::ImplicitModule;
5
6use std::rc::Rc;
7use std::cell::RefCell;
8
9pub struct RgbaSelect {
10    low: RgbaParameter,
11    high: RgbaParameter,
12    control: ScalarParameter,
13    threshold: ScalarParameter,
14    falloff: ScalarParameter,
15}
16
17impl RgbaSelect {
18    pub fn new() -> RgbaSelect {
19        RgbaSelect {
20            low: RgbaParameter::Constant(Rgba::with_value(0.0)),
21            high: RgbaParameter::Constant(Rgba::with_value(0.0)),
22            control: ScalarParameter::Value(0.0),
23            threshold: ScalarParameter::Value(0.0),
24            falloff: ScalarParameter::Value(0.0),
25        }
26    }
27
28    pub fn set_low_module(&mut self, m: Rc<RefCell<RgbaModule>>) {
29        self.low = RgbaParameter::Module(m);
30    }
31    pub fn set_low_value(&mut self, r: f32, g: f32, b: f32, a: f32) {
32        self.low = RgbaParameter::with_color(r, g, b, a);
33    }
34
35    pub fn set_high_module(&mut self, m: Rc<RefCell<RgbaModule>>) {
36        self.high = RgbaParameter::Module(m);
37    }
38    pub fn set_high_value(&mut self, r: f32, g: f32, b: f32, a: f32) {
39        self.high = RgbaParameter::with_color(r, g, b, a);
40    }
41
42    pub fn set_control_source_module(&mut self, b: Rc<RefCell<ImplicitModule>>) {
43        self.control = ScalarParameter::Source(b);
44    }
45
46    pub fn set_control_source_value(&mut self, v: f64) {
47        self.control = ScalarParameter::Value(v);
48    }
49
50    pub fn set_threshold_source_module(&mut self, b: Rc<RefCell<ImplicitModule>>) {
51        self.threshold = ScalarParameter::Source(b);
52    }
53
54    pub fn set_threshold_source_value(&mut self, v: f64) {
55        self.threshold = ScalarParameter::Value(v);
56    }
57
58    pub fn set_falloff_source_module(&mut self, b: Rc<RefCell<ImplicitModule>>) {
59        self.falloff = ScalarParameter::Source(b);
60    }
61
62    pub fn set_falloff_source_value(&mut self, v: f64) {
63        self.falloff = ScalarParameter::Value(v);
64    }
65}
66
67impl RgbaModule for RgbaSelect {
68    fn get_2d(&mut self, x: f64, y: f64) -> Rgba {
69        let s1 = self.low.get_2d(x, y);
70        let s2 = self.high.get_2d(x, y);
71        let control = self.control.get_2d(x, y);
72        let threshold = self.threshold.get_2d(x, y);
73        let falloff = self.falloff.get_2d(x, y);
74        get(&s1, &s2, control, threshold, falloff)
75    }
76    fn get_3d(&mut self, x: f64, y: f64, z: f64) -> Rgba {
77        let s1 = self.low.get_3d(x, y, z);
78        let s2 = self.high.get_3d(x, y, z);
79        let control = self.control.get_3d(x, y, z);
80        let threshold = self.threshold.get_3d(x, y, z);
81        let falloff = self.falloff.get_3d(x, y, z);
82        get(&s1, &s2, control, threshold, falloff)
83    }
84    fn get_4d(&mut self, x: f64, y: f64, z: f64, w: f64) -> Rgba {
85        let s1 = self.low.get_4d(x, y, z, w);
86        let s2 = self.high.get_4d(x, y, z, w);
87        let control = self.control.get_4d(x, y, z, w);
88        let threshold = self.threshold.get_4d(x, y, z, w);
89        let falloff = self.falloff.get_4d(x, y, z, w);
90        get(&s1, &s2, control, threshold, falloff)
91    }
92    fn get_6d(&mut self, x: f64, y: f64, z: f64, w: f64, u: f64, v: f64) -> Rgba {
93        let s1 = self.low.get_6d(x, y, z, w, u, v);
94        let s2 = self.high.get_6d(x, y, z, w, u, v);
95        let control = self.control.get_6d(x, y, z, w, u, v);
96        let threshold = self.threshold.get_6d(x, y, z, w, u, v);
97        let falloff = self.falloff.get_6d(x, y, z, w, u, v);
98        get(&s1, &s2, control, threshold, falloff)
99    }
100}
101
102#[inline(always)]
103fn get(s1: &Rgba, s2: &Rgba, control: f64, threshold: f64, falloff: f64) -> Rgba {
104    if falloff > 0.0 {
105        if control < (threshold - falloff) {
106            *s1
107        } else if control > (threshold + falloff) {
108            *s2
109        } else {
110            let lower = threshold - falloff;
111            let upper = threshold + falloff;
112            let t = quintic_blend((control - lower) / (upper - lower));
113            Rgba::with_all((s1[0] + t as f32 * (s2[0] - s1[0])) as f32,
114                           (s1[1] + t as f32 * (s2[1] - s1[1])) as f32,
115                           (s1[2] + t as f32 * (s2[2] - s1[2])) as f32,
116                           (s1[3] + t as f32 * (s2[3] - s1[3])) as f32)
117        }
118    } else {
119        if control < threshold { *s1 } else { *s2 }
120    }
121}