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 num::traits::Pow;

///
/// # Standard 3-D SPH kernel function object.
///
/// \see Müller, Matthias, David Charypar, and Markus Gross.
///     "Particle-based fluid simulation for interactive applications."
///     Proceedings of the 2003 ACM SIGGRAPH/Eurographics symposium on Computer
///     animation. Eurographics Association, 2003.
///
pub struct SphStdKernel3 {
    /// Kernel radius.
    pub h: f64,

    /// Square of the kernel radius.
    pub h2: f64,

    /// Cubic of the kernel radius.
    pub h3: f64,

    /// Fifth-power of the kernel radius.
    pub h5: f64,
}

impl SphStdKernel3 {
    /// Constructs a kernel object with zero radius.
    pub fn new_default() -> SphStdKernel3 {
        return SphStdKernel3 {
            h: 0.0,
            h2: 0.0,
            h3: 0.0,
            h5: 0.0,
        };
    }

    /// Constructs a kernel object with given radius.
    pub fn new(kernel_radius: f64) -> SphStdKernel3 {
        return SphStdKernel3 {
            h: kernel_radius,
            h2: kernel_radius.pow(2),
            h3: kernel_radius.pow(3),
            h5: kernel_radius.pow(5),
        };
    }

    /// Returns kernel function value at given distance.
    pub fn apply(&self, distance: f64) -> f64 {
        return if distance * distance >= self.h2 {
            0.0
        } else {
            let x = 1.0 - distance * distance / self.h2;
            315.0 / (64.0 * crate::constants::K_PI_D * self.h3) * x * x * x
        };
    }

    /// Returns the first derivative at given distance.
    pub fn first_derivative(&self, distance: f64) -> f64 {
        return if distance >= self.h {
            0.0
        } else {
            let x = 1.0 - distance * distance / self.h2;
            -945.0 / (32.0 * crate::constants::K_PI_D * self.h5) * distance * x * x
        };
    }

    /// Returns the gradient at a point.
    pub fn gradient_pnt(&self, point: &Vector3D) -> Vector3D {
        let dist = point.length();
        return if dist > 0.0 {
            self.gradient_dir(dist, &(*point / dist))
        } else {
            Vector3D::new_default()
        };
    }

    /// Returns the gradient at a point defined by distance and direction.
    pub fn gradient_dir(&self, distance: f64, direction: &Vector3D) -> Vector3D {
        return *direction * -self.first_derivative(distance);
    }

    /// Returns the second derivative at given distance.
    pub fn second_derivative(&self, distance: f64) -> f64 {
        return if distance * distance >= self.h2 {
            0.0
        } else {
            let x = distance * distance / self.h2;
            945.0 / (32.0 * crate::constants::K_PI_D * self.h5) * (1.0 - x) * (5.0 * x - 1.0)
        };
    }
}

///
/// # Spiky 3-D SPH kernel function object.
///
/// \see Müller, Matthias, David Charypar, and Markus Gross.
///     "Particle-based fluid simulation for interactive applications."
///     Proceedings of the 2003 ACM SIGGRAPH/Eurographics symposium on Computer
///     animation. Eurographics Association, 2003.
///
pub struct SphSpikyKernel3 {
    /// Kernel radius.
    pub h: f64,

    /// Square of the kernel radius.
    pub h2: f64,

    /// Cubic of the kernel radius.
    pub h3: f64,

    /// Fourth-power of the kernel radius.
    pub h4: f64,

    /// Fifth-power of the kernel radius.
    pub h5: f64,
}

impl SphSpikyKernel3 {
    /// Constructs a kernel object with zero radius.
    pub fn new_default() -> SphSpikyKernel3 {
        return SphSpikyKernel3 {
            h: 0.0,
            h2: 0.0,
            h3: 0.0,
            h4: 0.0,
            h5: 0.0,
        };
    }

    /// Constructs a kernel object with given radius.
    pub fn new(kernel_radius: f64) -> SphSpikyKernel3 {
        return SphSpikyKernel3 {
            h: kernel_radius,
            h2: kernel_radius.pow(2),
            h3: kernel_radius.pow(3),
            h4: kernel_radius.pow(4),
            h5: kernel_radius.pow(5),
        };
    }

    /// Returns kernel function value at given distance.
    pub fn apply(&self, distance: f64) -> f64 {
        return if distance >= self.h {
            0.0
        } else {
            let x = 1.0 - distance / self.h;
            15.0 / (crate::constants::K_PI_D * self.h3) * x * x * x
        };
    }

    /// Returns the first derivative at given distance.
    pub fn first_derivative(&self, distance: f64) -> f64 {
        return if distance >= self.h {
            0.0
        } else {
            let x = 1.0 - distance / self.h;
            -45.0 / (crate::constants::K_PI_D * self.h4) * x * x
        };
    }

    /// Returns the gradient at a point.
    pub fn gradient_pnt(&self, point: &Vector3D) -> Vector3D {
        let dist = point.length();
        return if dist > 0.0 {
            self.gradient_dir(dist, &(*point / dist))
        } else {
            Vector3D::new_default()
        };
    }

    /// Returns the gradient at a point defined by distance and direction.
    pub fn gradient_dir(&self, distance: f64, direction: &Vector3D) -> Vector3D {
        return *direction * -self.first_derivative(distance);
    }

    /// Returns the second derivative at given distance.
    pub fn second_derivative(&self, distance: f64) -> f64 {
        return if distance >= self.h {
            0.0
        } else {
            let x = 1.0 - distance / self.h;
            90.0 / (crate::constants::K_PI_D * self.h5) * x
        };
    }
}