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 std::sync::{RwLock, Arc};
use crate::field3::Field3;
use crate::scalar_field3::ScalarField3;

/// # 3-D scalar field with custom field function.
pub struct CustomScalarField3 {
    _custom_function: fn(&Vector3D) -> f64,
    _custom_gradient_function: Option<fn(&Vector3D) -> Vector3D>,
    _custom_laplacian_function: Option<fn(&Vector3D) -> f64>,
    _resolution: f64,
}

impl CustomScalarField3 {
    ///
    /// \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) -> f64,
               custom_gradient_function: Option<fn(&Vector3D) -> Vector3D>,
               custom_laplacian_function: Option<fn(&Vector3D) -> f64>,
               derivative_resolution: Option<f64>) -> CustomScalarField3 {
        return CustomScalarField3 {
            _custom_function: custom_function,
            _custom_gradient_function: custom_gradient_function,
            _custom_laplacian_function: custom_laplacian_function,
            _resolution: derivative_resolution.unwrap_or(1.0e-3),
        };
    }

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

impl Field3 for CustomScalarField3 {}

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

    fn gradient(&self, x: &Vector3D) -> Vector3D {
        return match self._custom_gradient_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)));

                return Vector3D::new(
                    (right - left) / self._resolution,
                    (top - bottom) / self._resolution,
                    (front - back) / self._resolution);
            }
            Some(func) => {
                func(x)
            }
        };
    }

    fn laplacian(&self, x: &Vector3D) -> f64 {
        return match self._custom_laplacian_function {
            None => {
                let center = (self._custom_function)(x);
                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)));

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

/// Shared pointer type for the CustomScalarField3.
pub type CustomScalarField3Ptr = Arc<RwLock<CustomScalarField3>>;

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

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

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

    /// Returns builder with curl function.
    pub fn with_laplacian_function(&mut self, func: fn(&Vector3D) -> f64) -> &mut Self {
        self._custom_laplacian_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 CustomScalarField3.
    pub fn build(&mut self) -> CustomScalarField3 {
        return CustomScalarField3::new(self._custom_function.unwrap(),
                                       self._custom_gradient_function,
                                       self._custom_laplacian_function,
                                       Some(self._resolution));
    }

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

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