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::vector2::Vector2D;
use crate::field2::Field2;
use crate::vector_field2::VectorField2;
use std::sync::{RwLock, Arc};

/// # 2-D vector field with custom field function.
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 {
    ///
    /// \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(&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),
        };
    }

    /// Returns builder fox CustomVectorField2.
    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);
            }
        }
    }
}

/// Shared pointer type for the CustomVectorField2.
pub type CustomVectorField2Ptr = Arc<RwLock<CustomVectorField2>>;

///
/// # Front-end to create CustomVectorField2 objects step by step.
///
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 {
    /// Returns builder with field function.
    pub fn with_function(&mut self,
                         func: fn(&Vector2D) -> Vector2D) -> &mut Self {
        self._custom_function = Some(func);
        return self;
    }

    /// Returns builder with divergence function.
    pub fn with_divergence_function(&mut self,
                                    func: fn(&Vector2D) -> 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(&Vector2D) -> f64) -> &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 CustomVectorField2.
    pub fn build(&mut self) -> CustomVectorField2 {
        return CustomVectorField2::new(self._custom_function.unwrap(),
                                       self._custom_divergence_function,
                                       self._custom_curl_function,
                                       Some(self._resolution));
    }

    /// Builds shared pointer of CustomVectorField2 instance.
    pub fn make_shared(&mut self) -> CustomVectorField2Ptr {
        return CustomVectorField2Ptr::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,
        };
    }
}