vox_geometry_rust 0.1.2

Geometry Tools for Rust
Documentation
/*
 * // Copyright (c) 2021 Feng Yang
 * //
 * // I am making my contributions/submissions to this project solely in my
 * // personal capacity and am not conveying any rights to any intellectual
 * // property of any third parties.
 */

use crate::vector3::Vector3D;
use crate::field3::Field3;
use crate::vector_field3::VectorField3;
use std::sync::{RwLock, Arc};

/// # 3-D vector field with custom field function.
pub struct CustomVectorField3 {
    _custom_function: fn(&Vector3D) -> Vector3D,
    _custom_divergence_function: Option<fn(&Vector3D) -> f64>,
    _custom_curl_function: Option<fn(&Vector3D) -> Vector3D>,
    _resolution: f64,
}

impl CustomVectorField3 {
    ///
    /// \brief Constructs a field with given function.
    ///
    /// This constructor creates a field with user-provided function object.
    /// To compute derivatives, such as gradient and Laplacian, finite
    /// differencing is used. Thus, the differencing resolution also can be
    /// provided as the last parameter.
    ///
    pub fn new(custom_function: fn(&Vector3D) -> Vector3D,
               custom_divergence_function: Option<fn(&Vector3D) -> f64>,
               custom_curl_function: Option<fn(&Vector3D) -> Vector3D>,
               derivative_resolution: Option<f64>) -> CustomVectorField3 {
        return CustomVectorField3 {
            _custom_function: custom_function,
            _custom_divergence_function: custom_divergence_function,
            _custom_curl_function: custom_curl_function,
            _resolution: derivative_resolution.unwrap_or(1.0e-3),
        };
    }

    /// Returns builder fox CustomVectorField3.
    pub fn builder() -> Builder {
        return Builder::new();
    }
}

impl Field3 for CustomVectorField3 {}

impl VectorField3 for CustomVectorField3 {
    fn sample(&self, x: &Vector3D) -> Vector3D {
        return (self._custom_function)(x);
    }

    fn divergence(&self, x: &Vector3D) -> f64 {
        return match self._custom_divergence_function {
            None => {
                let left
                    = (self._custom_function)(&(*x - Vector3D::new(0.5 * self._resolution, 0.0, 0.0))).x;
                let right
                    = (self._custom_function)(&(*x + Vector3D::new(0.5 * self._resolution, 0.0, 0.0))).x;
                let bottom
                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.5 * self._resolution, 0.0))).y;
                let top
                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.5 * self._resolution, 0.0))).y;
                let back
                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.0, 0.5 * self._resolution))).z;
                let front
                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.0, 0.5 * self._resolution))).z;

                (right - left + top - bottom + front - back) / self._resolution
            }
            Some(func) => {
                func(x)
            }
        };
    }

    fn curl(&self, x: &Vector3D) -> Vector3D {
        return match self._custom_curl_function {
            None => {
                let left
                    = (self._custom_function)(&(*x - Vector3D::new(0.5 * self._resolution, 0.0, 0.0)));
                let right
                    = (self._custom_function)(&(*x + Vector3D::new(0.5 * self._resolution, 0.0, 0.0)));
                let bottom
                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.5 * self._resolution, 0.0)));
                let top
                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.5 * self._resolution, 0.0)));
                let back
                    = (self._custom_function)(&(*x - Vector3D::new(0.0, 0.0, 0.5 * self._resolution)));
                let front
                    = (self._custom_function)(&(*x + Vector3D::new(0.0, 0.0, 0.5 * self._resolution)));

                let fx_ym = bottom.x;
                let fx_yp = top.x;
                let fx_zm = back.x;
                let fx_zp = front.x;

                let fy_xm = left.y;
                let fy_xp = right.y;
                let fy_zm = back.y;
                let fy_zp = front.y;

                let fz_xm = left.z;
                let fz_xp = right.z;
                let fz_ym = bottom.z;
                let fz_yp = top.z;

                Vector3D::new(
                    (fz_yp - fz_ym) - (fy_zp - fy_zm),
                    (fx_zp - fx_zm) - (fz_xp - fz_xm),
                    (fy_xp - fy_xm) - (fx_yp - fx_ym)) / self._resolution
            }
            Some(func) => {
                func(x)
            }
        };
    }
}

/// Shared pointer type for the CustomVectorField3.
pub type CustomVectorField3Ptr = Arc<RwLock<CustomVectorField3>>;

///
/// # Front-end to create CustomVectorField3 objects step by step.
///
pub struct Builder {
    _custom_function: Option<fn(&Vector3D) -> Vector3D>,
    _custom_divergence_function: Option<fn(&Vector3D) -> f64>,
    _custom_curl_function: Option<fn(&Vector3D) -> Vector3D>,
    _resolution: f64,
}

impl Builder {
    /// Returns builder with field function.
    pub fn with_function(&mut self,
                         func: fn(&Vector3D) -> Vector3D) -> &mut Self {
        self._custom_function = Some(func);
        return self;
    }

    /// Returns builder with divergence function.
    pub fn with_divergence_function(&mut self,
                                    func: fn(&Vector3D) -> f64) -> &mut Self {
        self._custom_divergence_function = Some(func);
        return self;
    }

    /// Returns builder with curl function.
    pub fn with_curl_function(&mut self,
                              func: fn(&Vector3D) -> Vector3D) -> &mut Self {
        self._custom_curl_function = Some(func);
        return self;
    }

    /// Returns builder with derivative resolution.
    pub fn with_derivative_resolution(&mut self, resolution: f64) -> &mut Self {
        self._resolution = resolution;
        return self;
    }

    /// Builds CustomVectorField3.
    pub fn build(&mut self) -> CustomVectorField3 {
        return CustomVectorField3::new(self._custom_function.unwrap(),
                                       self._custom_divergence_function,
                                       self._custom_curl_function,
                                       Some(self._resolution));
    }

    /// Builds shared pointer of CustomVectorField3 instance.
    pub fn make_shared(&mut self) -> CustomVectorField3Ptr {
        return CustomVectorField3Ptr::new(RwLock::new(self.build()));
    }

    /// constructor
    pub fn new() -> Builder {
        return Builder {
            _custom_function: None,
            _custom_divergence_function: None,
            _custom_curl_function: None,
            _resolution: 1.0e-3,
        };
    }
}