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::surface3::*;
use crate::vector3::Vector3D;
use crate::transform3::Transform3;
use crate::bounding_box3::BoundingBox3D;
use crate::ray3::Ray3D;
use std::sync::{RwLock, Arc};

///
/// # 3-D plane geometry.
///
/// This class represents 3-D plane geometry which extends Surface3 by
/// overriding surface-related queries.
///
pub struct Plane3 {
    /// Plane normal.
    pub normal: Vector3D,

    /// Point that lies on the plane.
    pub point: Vector3D,

    /// data from surface3
    pub surface_data: Surface3Data,
}

impl Plane3 {
    /// Constructs a plane that crosses (0, 0) with surface normal (0, 1).
    pub fn new_default(transform: Option<Transform3>,
                       is_normal_flipped: Option<bool>) -> Plane3 {
        return Plane3 {
            normal: Vector3D::new(0.0, 1.0, 0.0),
            point: Vector3D::new_default(),
            surface_data: Surface3Data::new(transform, is_normal_flipped),
        };
    }

    /// Constructs a plane that cross \p point with surface normal \p normal.
    pub fn new(normal: Vector3D,
               point: Vector3D,
               transform: Option<Transform3>,
               is_normal_flipped: Option<bool>) -> Plane3 {
        return Plane3 {
            normal,
            point,
            surface_data: Surface3Data::new(transform, is_normal_flipped),
        };
    }

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

impl Surface3 for Plane3 {
    fn closest_point_local(&self, other_point: &Vector3D) -> Vector3D {
        let r = *other_point - self.point;
        return r - self.normal * self.normal.dot(&r) + self.point;
    }

    fn bounding_box_local(&self) -> BoundingBox3D {
        let eps = f64::EPSILON;
        let dmax = f64::MAX;

        return if f64::abs(self.normal.dot(&Vector3D::new(1.0, 0.0, 0.0)) - 1.0) < eps {
            BoundingBox3D::new(self.point - Vector3D::new(0.0, dmax, dmax),
                               self.point + Vector3D::new(0.0, dmax, dmax))
        } else if f64::abs(self.normal.dot(&Vector3D::new(0.0, 1.0, 0.0)) - 1.0) < eps {
            BoundingBox3D::new(self.point - Vector3D::new(dmax, 0.0, dmax),
                               self.point + Vector3D::new(dmax, 0.0, dmax))
        } else if f64::abs(self.normal.dot(&Vector3D::new(0.0, 0.0, 1.0)) - 1.0) < eps {
            BoundingBox3D::new(self.point - Vector3D::new(dmax, dmax, 0.0),
                               self.point + Vector3D::new(dmax, dmax, 0.0))
        } else {
            BoundingBox3D::new(Vector3D::new(dmax, dmax, dmax),
                               Vector3D::new(dmax, dmax, dmax))
        };
    }

    fn closest_intersection_local(&self, ray: &Ray3D) -> SurfaceRayIntersection3 {
        let mut intersection = SurfaceRayIntersection3::new();
        let d_dot_n = ray.direction.dot(&self.normal);

        // Check if not parallel
        if f64::abs(d_dot_n) > 0.0 {
            let t = self.normal.dot(&(self.point - ray.origin)) / d_dot_n;
            if t >= 0.0 {
                intersection.is_intersecting = true;
                intersection.distance = t;
                intersection.point = ray.point_at(t);
                intersection.normal = self.normal;
            }
        }

        return intersection;
    }

    fn closest_normal_local(&self, _other_point: &Vector3D) -> Vector3D {
        return self.normal;
    }

    fn intersects_local(&self, ray_local: &Ray3D) -> bool {
        return f64::abs(ray_local.direction.dot(&self.normal)) > 0.0;
    }

    fn view(&self) -> &Surface3Data {
        return &self.surface_data;
    }
}

/// Shared pointer for the Plane3 type.
pub type Plane3Ptr = Arc<RwLock<Plane3>>;

///
/// # Front-end to create Plane3 objects step by step.
///
pub struct Builder {
    _normal: Vector3D,
    _point: Vector3D,

    _surface_data: Surface3Data,
}

impl Builder {
    /// Returns builder with plane normal.
    pub fn with_normal(&mut self, normal: Vector3D) -> &mut Self {
        self._normal = normal;
        return self;
    }

    /// Returns builder with point on the plane.
    pub fn with_point(&mut self, point: Vector3D) -> &mut Self {
        self._point = point;
        return self;
    }

    /// Builds Plane3.
    pub fn build(&mut self) -> Plane3 {
        return Plane3::new(self._normal,
                           self._point,
                           Some(self._surface_data.transform.clone()),
                           Some(self._surface_data.is_normal_flipped),
        );
    }

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

    /// constructor
    pub fn new() -> Builder {
        return Builder {
            _normal: Vector3D::new(0.0, 1.0, 0.0),
            _point: Vector3D::new_default(),
            _surface_data: Surface3Data::new(None, None),
        };
    }
}

impl SurfaceBuilderBase3 for Builder {
    fn view(&mut self) -> &mut Surface3Data {
        return &mut self._surface_data;
    }
}