autd3/gain/
plane.rs

1use autd3_core::derive::*;
2
3use autd3_driver::{common::rad, geometry::UnitVector3};
4
5/// The option of [`Plane`].
6#[derive(Debug, Clone, Copy, PartialEq)]
7#[repr(C)]
8pub struct PlaneOption {
9    /// The intensity of the wave.
10    pub intensity: Intensity,
11    /// The phase offset of the wave.
12    pub phase_offset: Phase,
13}
14
15impl Default for PlaneOption {
16    fn default() -> Self {
17        Self {
18            intensity: Intensity::MAX,
19            phase_offset: Phase::ZERO,
20        }
21    }
22}
23
24/// Plane wave
25#[derive(Gain, Clone, PartialEq, Debug)]
26pub struct Plane {
27    /// The direction of the plane wave.
28    pub dir: UnitVector3,
29    /// The option of the gain.
30    pub option: PlaneOption,
31}
32
33impl Plane {
34    /// Create a new [`Plane`].
35    #[must_use]
36    pub const fn new(dir: UnitVector3, option: PlaneOption) -> Self {
37        Self { dir, option }
38    }
39}
40
41#[derive(Clone, Copy)]
42pub struct Impl {
43    dir: UnitVector3,
44    intensity: Intensity,
45    phase_offset: Phase,
46    wavenumber: f32,
47}
48
49impl GainCalculator<'_> for Impl {
50    fn calc(&self, tr: &Transducer) -> Drive {
51        Drive {
52            phase: Phase::from(-self.dir.dot(&tr.position().coords) * self.wavenumber * rad)
53                + self.phase_offset,
54            intensity: self.intensity,
55        }
56    }
57}
58
59impl GainCalculatorGenerator<'_> for Impl {
60    type Calculator = Impl;
61
62    fn generate(&mut self, _: &Device) -> Self::Calculator {
63        *self
64    }
65}
66
67impl Gain<'_> for Plane {
68    type G = Impl;
69
70    fn init(
71        self,
72        _: &Geometry,
73        env: &Environment,
74        _: &TransducerMask,
75    ) -> Result<Self::G, GainError> {
76        Ok(Impl {
77            dir: self.dir,
78            intensity: self.option.intensity,
79            phase_offset: self.option.phase_offset,
80            wavenumber: env.wavenumber(),
81        })
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use rand::Rng;
88
89    use super::*;
90
91    use crate::tests::{create_geometry, random_vector3};
92
93    fn plane_check(
94        mut b: Impl,
95        dir: UnitVector3,
96        intensity: Intensity,
97        phase_offset: Phase,
98        geometry: &Geometry,
99        env: &Environment,
100    ) {
101        geometry.iter().for_each(|dev| {
102            let d = b.generate(dev);
103            dev.iter().for_each(|tr| {
104                let expected_phase =
105                    Phase::from(-dir.dot(&tr.position().coords) * env.wavenumber() * rad)
106                        + phase_offset;
107                let d = d.calc(tr);
108                assert_eq!(expected_phase, d.phase);
109                assert_eq!(intensity, d.intensity);
110            });
111        });
112    }
113
114    #[test]
115    fn plane() {
116        let mut rng = rand::rng();
117
118        let geometry = create_geometry(1);
119        let env = Environment::new();
120
121        let dir = UnitVector3::new_normalize(random_vector3(-1.0..1.0, -1.0..1.0, -1.0..1.0));
122        let g = Plane::new(dir, PlaneOption::default());
123        plane_check(
124            g.init(&geometry, &env, &TransducerMask::AllEnabled)
125                .unwrap(),
126            dir,
127            Intensity::MAX,
128            Phase::ZERO,
129            &geometry,
130            &env,
131        );
132
133        let dir = UnitVector3::new_normalize(random_vector3(-1.0..1.0, -1.0..1.0, -1.0..1.0));
134        let intensity = Intensity(rng.random());
135        let phase_offset = Phase(rng.random());
136        let g = Plane {
137            dir,
138            option: PlaneOption {
139                intensity,
140                phase_offset,
141            },
142        };
143        plane_check(
144            g.init(&geometry, &env, &TransducerMask::AllEnabled)
145                .unwrap(),
146            dir,
147            intensity,
148            phase_offset,
149            &geometry,
150            &env,
151        );
152    }
153}