use crate::vector2::Vector2D;
use crate::field2::Field2;
use crate::vector_field2::VectorField2;
use std::sync::{RwLock, Arc};
pub struct CustomVectorField2 {
_custom_function: fn(&Vector2D) -> Vector2D,
_custom_divergence_function: Option<fn(&Vector2D) -> f64>,
_custom_curl_function: Option<fn(&Vector2D) -> f64>,
_resolution: f64,
}
impl CustomVectorField2 {
pub fn new(custom_function: fn(&Vector2D) -> Vector2D,
custom_divergence_function: Option<fn(&Vector2D) -> f64>,
custom_curl_function: Option<fn(&Vector2D) -> f64>,
derivative_resolution: Option<f64>) -> CustomVectorField2 {
return CustomVectorField2 {
_custom_function: custom_function,
_custom_divergence_function: custom_divergence_function,
_custom_curl_function: custom_curl_function,
_resolution: derivative_resolution.unwrap_or(1.0e-3),
};
}
pub fn builder() -> Builder {
return Builder::new();
}
}
impl Field2 for CustomVectorField2 {}
impl VectorField2 for CustomVectorField2 {
fn sample(&self, x: &Vector2D) -> Vector2D {
return (self._custom_function)(x);
}
fn divergence(&self, x: &Vector2D) -> f64 {
return match self._custom_divergence_function {
None => {
let left = (self._custom_function)(&(*x - Vector2D::new(0.5 * self._resolution, 0.0))).x;
let right = (self._custom_function)(&(*x + Vector2D::new(0.5 * self._resolution, 0.0))).x;
let bottom = (self._custom_function)(&(*x - Vector2D::new(0.0, 0.5 * self._resolution))).y;
let top = (self._custom_function)(&(*x + Vector2D::new(0.0, 0.5 * self._resolution))).y;
(right - left + top - bottom) / self._resolution
}
Some(func) => {
func(x)
}
};
}
fn curl(&self, x: &Vector2D) -> f64 {
match self._custom_curl_function {
None => {
let left = (self._custom_function)(&(*x - Vector2D::new(0.5 * self._resolution, 0.0))).y;
let right = (self._custom_function)(&(*x + Vector2D::new(0.5 * self._resolution, 0.0))).y;
let bottom = (self._custom_function)(&(*x - Vector2D::new(0.0, 0.5 * self._resolution))).x;
let top = (self._custom_function)(&(*x + Vector2D::new(0.0, 0.5 * self._resolution))).x;
return (top - bottom - right + left) / self._resolution;
}
Some(func) => {
return func(x);
}
}
}
}
pub type CustomVectorField2Ptr = Arc<RwLock<CustomVectorField2>>;
pub struct Builder {
_custom_function: Option<fn(&Vector2D) -> Vector2D>,
_custom_divergence_function: Option<fn(&Vector2D) -> f64>,
_custom_curl_function: Option<fn(&Vector2D) -> f64>,
_resolution: f64,
}
impl Builder {
pub fn with_function(&mut self,
func: fn(&Vector2D) -> Vector2D) -> &mut Self {
self._custom_function = Some(func);
return self;
}
pub fn with_divergence_function(&mut self,
func: fn(&Vector2D) -> f64) -> &mut Self {
self._custom_divergence_function = Some(func);
return self;
}
pub fn with_curl_function(&mut self,
func: fn(&Vector2D) -> f64) -> &mut Self {
self._custom_curl_function = Some(func);
return self;
}
pub fn with_derivative_resolution(&mut self, resolution: f64) -> &mut Self {
self._resolution = resolution;
return self;
}
pub fn build(&mut self) -> CustomVectorField2 {
return CustomVectorField2::new(self._custom_function.unwrap(),
self._custom_divergence_function,
self._custom_curl_function,
Some(self._resolution));
}
pub fn make_shared(&mut self) -> CustomVectorField2Ptr {
return CustomVectorField2Ptr::new(RwLock::new(self.build()));
}
pub fn new() -> Builder {
return Builder {
_custom_function: None,
_custom_divergence_function: None,
_custom_curl_function: None,
_resolution: 1.0e-3,
};
}
}