vox_geometry_rust/
custom_vector_field3.rs

1/*
2 * // Copyright (c) 2021 Feng Yang
3 * //
4 * // I am making my contributions/submissions to this project solely in my
5 * // personal capacity and am not conveying any rights to any intellectual
6 * // property of any third parties.
7 */
8
9use crate::vector3::Vector3D;
10use crate::field3::Field3;
11use crate::vector_field3::VectorField3;
12use std::sync::{RwLock, Arc};
13
14/// # 3-D vector field with custom field function.
15pub struct CustomVectorField3 {
16    _custom_function: fn(&Vector3D) -> Vector3D,
17    _custom_divergence_function: Option<fn(&Vector3D) -> f64>,
18    _custom_curl_function: Option<fn(&Vector3D) -> Vector3D>,
19    _resolution: f64,
20}
21
22impl CustomVectorField3 {
23    ///
24    /// \brief Constructs a field with given function.
25    ///
26    /// This constructor creates a field with user-provided function object.
27    /// To compute derivatives, such as gradient and Laplacian, finite
28    /// differencing is used. Thus, the differencing resolution also can be
29    /// provided as the last parameter.
30    ///
31    pub fn new(custom_function: fn(&Vector3D) -> Vector3D,
32               custom_divergence_function: Option<fn(&Vector3D) -> f64>,
33               custom_curl_function: Option<fn(&Vector3D) -> Vector3D>,
34               derivative_resolution: Option<f64>) -> CustomVectorField3 {
35        return CustomVectorField3 {
36            _custom_function: custom_function,
37            _custom_divergence_function: custom_divergence_function,
38            _custom_curl_function: custom_curl_function,
39            _resolution: derivative_resolution.unwrap_or(1.0e-3),
40        };
41    }
42
43    /// Returns builder fox CustomVectorField3.
44    pub fn builder() -> Builder {
45        return Builder::new();
46    }
47}
48
49impl Field3 for CustomVectorField3 {}
50
51impl VectorField3 for CustomVectorField3 {
52    fn sample(&self, x: &Vector3D) -> Vector3D {
53        return (self._custom_function)(x);
54    }
55
56    fn divergence(&self, x: &Vector3D) -> f64 {
57        return match self._custom_divergence_function {
58            None => {
59                let left
60                    = (self._custom_function)(&(*x - Vector3D::new(0.5 * self._resolution, 0.0, 0.0))).x;
61                let right
62                    = (self._custom_function)(&(*x + Vector3D::new(0.5 * self._resolution, 0.0, 0.0))).x;
63                let bottom
64                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.5 * self._resolution, 0.0))).y;
65                let top
66                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.5 * self._resolution, 0.0))).y;
67                let back
68                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.0, 0.5 * self._resolution))).z;
69                let front
70                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.0, 0.5 * self._resolution))).z;
71
72                (right - left + top - bottom + front - back) / self._resolution
73            }
74            Some(func) => {
75                func(x)
76            }
77        };
78    }
79
80    fn curl(&self, x: &Vector3D) -> Vector3D {
81        return match self._custom_curl_function {
82            None => {
83                let left
84                    = (self._custom_function)(&(*x - Vector3D::new(0.5 * self._resolution, 0.0, 0.0)));
85                let right
86                    = (self._custom_function)(&(*x + Vector3D::new(0.5 * self._resolution, 0.0, 0.0)));
87                let bottom
88                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.5 * self._resolution, 0.0)));
89                let top
90                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.5 * self._resolution, 0.0)));
91                let back
92                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.0, 0.5 * self._resolution)));
93                let front
94                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.0, 0.5 * self._resolution)));
95
96                let fx_ym = bottom.x;
97                let fx_yp = top.x;
98                let fx_zm = back.x;
99                let fx_zp = front.x;
100
101                let fy_xm = left.y;
102                let fy_xp = right.y;
103                let fy_zm = back.y;
104                let fy_zp = front.y;
105
106                let fz_xm = left.z;
107                let fz_xp = right.z;
108                let fz_ym = bottom.z;
109                let fz_yp = top.z;
110
111                Vector3D::new(
112                    (fz_yp - fz_ym) - (fy_zp - fy_zm),
113                    (fx_zp - fx_zm) - (fz_xp - fz_xm),
114                    (fy_xp - fy_xm) - (fx_yp - fx_ym)) / self._resolution
115            }
116            Some(func) => {
117                func(x)
118            }
119        };
120    }
121}
122
123/// Shared pointer type for the CustomVectorField3.
124pub type CustomVectorField3Ptr = Arc<RwLock<CustomVectorField3>>;
125
126///
127/// # Front-end to create CustomVectorField3 objects step by step.
128///
129pub struct Builder {
130    _custom_function: Option<fn(&Vector3D) -> Vector3D>,
131    _custom_divergence_function: Option<fn(&Vector3D) -> f64>,
132    _custom_curl_function: Option<fn(&Vector3D) -> Vector3D>,
133    _resolution: f64,
134}
135
136impl Builder {
137    /// Returns builder with field function.
138    pub fn with_function(&mut self,
139                         func: fn(&Vector3D) -> Vector3D) -> &mut Self {
140        self._custom_function = Some(func);
141        return self;
142    }
143
144    /// Returns builder with divergence function.
145    pub fn with_divergence_function(&mut self,
146                                    func: fn(&Vector3D) -> f64) -> &mut Self {
147        self._custom_divergence_function = Some(func);
148        return self;
149    }
150
151    /// Returns builder with curl function.
152    pub fn with_curl_function(&mut self,
153                              func: fn(&Vector3D) -> Vector3D) -> &mut Self {
154        self._custom_curl_function = Some(func);
155        return self;
156    }
157
158    /// Returns builder with derivative resolution.
159    pub fn with_derivative_resolution(&mut self, resolution: f64) -> &mut Self {
160        self._resolution = resolution;
161        return self;
162    }
163
164    /// Builds CustomVectorField3.
165    pub fn build(&mut self) -> CustomVectorField3 {
166        return CustomVectorField3::new(self._custom_function.unwrap(),
167                                       self._custom_divergence_function,
168                                       self._custom_curl_function,
169                                       Some(self._resolution));
170    }
171
172    /// Builds shared pointer of CustomVectorField3 instance.
173    pub fn make_shared(&mut self) -> CustomVectorField3Ptr {
174        return CustomVectorField3Ptr::new(RwLock::new(self.build()));
175    }
176
177    /// constructor
178    pub fn new() -> Builder {
179        return Builder {
180            _custom_function: None,
181            _custom_divergence_function: None,
182            _custom_curl_function: None,
183            _resolution: 1.0e-3,
184        };
185    }
186}