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

/// Struct that represents ray-surface intersection point.
pub struct SurfaceRayIntersection3 {
    pub is_intersecting: bool,
    pub distance: f64,
    pub point: Vector3D,
    pub normal: Vector3D,
}

impl SurfaceRayIntersection3 {
    pub fn new() -> SurfaceRayIntersection3 {
        return SurfaceRayIntersection3 {
            is_intersecting: false,
            distance: f64::MAX,
            point: Vector3D::new_default(),
            normal: Vector3D::new_default(),
        };
    }
}

pub struct Surface3Data {
    /// Local-to-world transform.
    pub transform: Transform3,

    /// Flips normal.
    pub is_normal_flipped: bool,
}

impl Surface3Data {
    pub fn new(transform: Option<Transform3>,
               is_normal_flipped: Option<bool>) -> Surface3Data {
        return Surface3Data {
            transform: transform.unwrap_or(Transform3::new_default()),
            is_normal_flipped: is_normal_flipped.unwrap_or(false),
        };
    }
}

/// Abstract base class for 3-D surface.
pub trait Surface3 {
    /// Returns the closest point from the given point \p other_point to the
    /// surface in local frame.
    fn closest_point_local(&self, other_point: &Vector3D) -> Vector3D;

    /// Returns the bounding box of this surface object in local frame.
    fn bounding_box_local(&self) -> BoundingBox3D;

    /// Returns the closest intersection point for given \p ray in local frame.
    fn closest_intersection_local(&self, ray: &Ray3D) -> SurfaceRayIntersection3;

    /// Returns the normal to the closest point on the surface from the given
    /// point \p other_point in local frame.
    fn closest_normal_local(&self, other_point: &Vector3D) -> Vector3D;

    /// Returns true if the given \p ray intersects with this surface object
    /// in local frame.
    fn intersects_local(&self, ray_local: &Ray3D) -> bool {
        let result = self.closest_intersection_local(ray_local);
        return result.is_intersecting;
    }

    /// Returns the closest distance from the given point \p otherPoint to the
    /// point on the surface in local frame.
    fn closest_distance_local(&self, other_point_local: &Vector3D) -> f64 {
        return other_point_local.distance_to(self.closest_point_local(other_point_local));
    }

    /// Returns true if \p otherPoint is inside by given \p depth the volume
    /// defined by the surface in local frame.
    fn is_inside_local(&self, other_point_local: &Vector3D) -> bool {
        let cp_local = self.closest_point_local(other_point_local);
        let normal_local = self.closest_normal_local(other_point_local);
        return (*other_point_local - cp_local).dot(&normal_local) < 0.0;
    }

    //----------------------------------------------------------------------------------------------
    /// Returns the closest point from the given point \p other_point to the surface.
    fn closest_point(&self, other_point: &Vector3D) -> Vector3D {
        return self.view().transform.to_world_vec(&self.closest_point_local(
            &self.view().transform.to_local_vec(&other_point)));
    }

    /// Returns the bounding box of this surface object.
    fn bounding_box(&self) -> BoundingBox3D {
        return self.view().transform.to_world_aabb(&self.bounding_box_local());
    }

    /// Returns true if the given \p ray intersects with this surface object.
    fn intersects(&self, ray: &Ray3D) -> bool {
        return self.intersects_local(&self.view().transform.to_local_ray(&ray));
    }

    /// Returns the closest distance from the given point \p other_point to the
    /// point on the surface.
    fn closest_distance(&self, other_point: &Vector3D) -> f64 {
        return self.closest_distance_local(&self.view().transform.to_local_vec(&other_point));
    }

    /// Returns the closest intersection point for given \p ray.
    fn closest_intersection(&self, ray: &Ray3D) -> SurfaceRayIntersection3 {
        let mut result = self.closest_intersection_local(
            &self.view().transform.to_local_ray(&ray));
        result.point = self.view().transform.to_world_vec(&result.point);
        result.normal = self.view().transform.to_world_direction(&result.normal);
        match self.view().is_normal_flipped {
            true => result.normal *= -1.0,
            _ => {}
        }
        return result;
    }

    /// Returns the normal to the closest point on the surface from the given
    /// point \p other_point.
    fn closest_normal(&self, other_point: &Vector3D) -> Vector3D {
        let mut result = self.view().transform.to_world_direction(
            &self.closest_normal_local(
                &self.view().transform.to_local_vec(&other_point)));
        match self.view().is_normal_flipped {
            true => result *= -1.0,
            _ => {}
        }
        return result;
    }

    /// Updates internal spatial query engine.
    fn update_query_engine(&self) {}

    /// Returns true if bounding box can be defined.
    fn is_bounded(&self) -> bool {
        return true;
    }

    /// Returns true if the surface is a valid geometry.
    fn is_valid_geometry(&self) -> bool {
        return true;
    }

    /// Returns true if \p other_point is inside the volume defined by the surface.
    fn is_inside(&self, other_point: &Vector3D) -> bool {
        return self.view().is_normal_flipped == !self.is_inside_local(
            &self.view().transform.to_local_vec(&other_point));
    }

    //----------------------------------------------------------------------------------------------
    fn view(&self) -> &Surface3Data;
}

/// Shared pointer for the Surface3 type.
pub type Surface3Ptr = Arc<RwLock<dyn Surface3>>;

///
/// # Base class for 3-D surface builder.
///
pub trait SurfaceBuilderBase3 {
    /// Returns builder with flipped normal flag.
    fn with_is_normal_flipped(&mut self, is_normal_flipped: bool) -> &mut Self {
        self.view().is_normal_flipped = is_normal_flipped;
        return self;
    }

    /// Returns builder with translation.
    fn with_translation(&mut self, translation: Vector3D) -> &mut Self {
        self.view().transform.set_translation(translation);
        return self;
    }

    /// Returns builder with orientation.
    fn with_orientation(&mut self, orientation: QuaternionD) -> &mut Self {
        self.view().transform.set_orientation(orientation);
        return self;
    }

    /// Returns builder with transform.
    fn with_transform(&mut self, transform: Transform3) -> &mut Self {
        self.view().transform = transform;
        return self;
    }

    //----------------------------------------------------------------------------------------------
    fn view(&mut self) -> &mut Surface3Data;
}