vox_geometry_rust/
custom_vector_field2.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::vector2::Vector2D;
10use crate::field2::Field2;
11use crate::vector_field2::VectorField2;
12use std::sync::{RwLock, Arc};
13
14/// # 2-D vector field with custom field function.
15pub struct CustomVectorField2 {
16    _custom_function: fn(&Vector2D) -> Vector2D,
17    _custom_divergence_function: Option<fn(&Vector2D) -> f64>,
18    _custom_curl_function: Option<fn(&Vector2D) -> f64>,
19    _resolution: f64,
20}
21
22impl CustomVectorField2 {
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(&Vector2D) -> Vector2D,
32               custom_divergence_function: Option<fn(&Vector2D) -> f64>,
33               custom_curl_function: Option<fn(&Vector2D) -> f64>,
34               derivative_resolution: Option<f64>) -> CustomVectorField2 {
35        return CustomVectorField2 {
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 CustomVectorField2.
44    pub fn builder() -> Builder {
45        return Builder::new();
46    }
47}
48
49impl Field2 for CustomVectorField2 {}
50
51impl VectorField2 for CustomVectorField2 {
52    fn sample(&self, x: &Vector2D) -> Vector2D {
53        return (self._custom_function)(x);
54    }
55
56    fn divergence(&self, x: &Vector2D) -> f64 {
57        return match self._custom_divergence_function {
58            None => {
59                let left = (self._custom_function)(&(*x - Vector2D::new(0.5 * self._resolution, 0.0))).x;
60                let right = (self._custom_function)(&(*x + Vector2D::new(0.5 * self._resolution, 0.0))).x;
61                let bottom = (self._custom_function)(&(*x - Vector2D::new(0.0, 0.5 * self._resolution))).y;
62                let top = (self._custom_function)(&(*x + Vector2D::new(0.0, 0.5 * self._resolution))).y;
63
64                (right - left + top - bottom) / self._resolution
65            }
66            Some(func) => {
67                func(x)
68            }
69        };
70    }
71
72    fn curl(&self, x: &Vector2D) -> f64 {
73        match self._custom_curl_function {
74            None => {
75                let left = (self._custom_function)(&(*x - Vector2D::new(0.5 * self._resolution, 0.0))).y;
76                let right = (self._custom_function)(&(*x + Vector2D::new(0.5 * self._resolution, 0.0))).y;
77                let bottom = (self._custom_function)(&(*x - Vector2D::new(0.0, 0.5 * self._resolution))).x;
78                let top = (self._custom_function)(&(*x + Vector2D::new(0.0, 0.5 * self._resolution))).x;
79
80                return (top - bottom - right + left) / self._resolution;
81            }
82            Some(func) => {
83                return func(x);
84            }
85        }
86    }
87}
88
89/// Shared pointer type for the CustomVectorField2.
90pub type CustomVectorField2Ptr = Arc<RwLock<CustomVectorField2>>;
91
92///
93/// # Front-end to create CustomVectorField2 objects step by step.
94///
95pub struct Builder {
96    _custom_function: Option<fn(&Vector2D) -> Vector2D>,
97    _custom_divergence_function: Option<fn(&Vector2D) -> f64>,
98    _custom_curl_function: Option<fn(&Vector2D) -> f64>,
99    _resolution: f64,
100}
101
102impl Builder {
103    /// Returns builder with field function.
104    pub fn with_function(&mut self,
105                         func: fn(&Vector2D) -> Vector2D) -> &mut Self {
106        self._custom_function = Some(func);
107        return self;
108    }
109
110    /// Returns builder with divergence function.
111    pub fn with_divergence_function(&mut self,
112                                    func: fn(&Vector2D) -> f64) -> &mut Self {
113        self._custom_divergence_function = Some(func);
114        return self;
115    }
116
117    /// Returns builder with curl function.
118    pub fn with_curl_function(&mut self,
119                              func: fn(&Vector2D) -> f64) -> &mut Self {
120        self._custom_curl_function = Some(func);
121        return self;
122    }
123
124    /// Returns builder with derivative resolution.
125    pub fn with_derivative_resolution(&mut self, resolution: f64) -> &mut Self {
126        self._resolution = resolution;
127        return self;
128    }
129
130    /// Builds CustomVectorField2.
131    pub fn build(&mut self) -> CustomVectorField2 {
132        return CustomVectorField2::new(self._custom_function.unwrap(),
133                                       self._custom_divergence_function,
134                                       self._custom_curl_function,
135                                       Some(self._resolution));
136    }
137
138    /// Builds shared pointer of CustomVectorField2 instance.
139    pub fn make_shared(&mut self) -> CustomVectorField2Ptr {
140        return CustomVectorField2Ptr::new(RwLock::new(self.build()));
141    }
142
143    /// constructor
144    pub fn new() -> Builder {
145        return Builder {
146            _custom_function: None,
147            _custom_divergence_function: None,
148            _custom_curl_function: None,
149            _resolution: 1.0e-3,
150        };
151    }
152}