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::bvh3::Bvh3;
use crate::implicit_surface3::*;
use crate::surface3::*;
use crate::vector3::Vector3D;
use crate::transform3::Transform3;
use crate::bounding_box3::BoundingBox3D;
use crate::ray3::Ray3D;
use crate::surface_to_implicit3::SurfaceToImplicit3;
use crate::nearest_neighbor_query_engine3::NearestNeighborQueryEngine3;
use crate::intersection_query_engine3::IntersectionQueryEngine3;
use std::sync::{RwLock, Arc};

///
/// # 3-D implicit surface set.
///
/// This class represents 3-D implicit surface set which extends
/// ImplicitSurface3 by overriding implicit surface-related quries. This is
/// class can hold a collection of other implicit surface instances.
///
pub struct ImplicitSurfaceSet3 {
    _surfaces: Vec<ImplicitSurface3Ptr>,
    _unbounded_surfaces: Vec<ImplicitSurface3Ptr>,
    _bvh: RwLock<Bvh3<ImplicitSurface3Ptr>>,
    _bvh_invalidated: RwLock<bool>,

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

impl ImplicitSurfaceSet3 {
    /// Constructs an empty implicit surface set.
    pub fn new_default() -> ImplicitSurfaceSet3 {
        return ImplicitSurfaceSet3 {
            _surfaces: vec![],
            _unbounded_surfaces: vec![],
            _bvh: RwLock::new(Bvh3::new()),
            _bvh_invalidated: RwLock::new(true),
            surface_data: Surface3Data::new(None, None),
        };
    }

    /// Constructs an implicit surface set using list of other surfaces.
    pub fn new(surfaces: Vec<ImplicitSurface3Ptr>,
               transform: Option<Transform3>,
               is_normal_flipped: Option<bool>) -> ImplicitSurfaceSet3 {
        let mut unbounded_surfaces: Vec<ImplicitSurface3Ptr> = vec![];
        for surface in &surfaces {
            if !surface.read().unwrap().is_bounded() {
                unbounded_surfaces.push(surface.clone());
            }
        }

        return ImplicitSurfaceSet3 {
            _surfaces: surfaces,
            _unbounded_surfaces: unbounded_surfaces,
            _bvh: RwLock::new(Bvh3::new()),
            _bvh_invalidated: RwLock::new(true),
            surface_data: Surface3Data::new(transform, is_normal_flipped),
        };
    }

    /// Constructs an implicit surface set using list of other surfaces.
    pub fn new_explicit(surfaces: Vec<Surface3Ptr>,
                        transform: Option<Transform3>,
                        is_normal_flipped: Option<bool>) -> ImplicitSurfaceSet3 {
        let mut set = ImplicitSurfaceSet3::new_default();
        set.surface_data.transform = transform.unwrap_or(Transform3::new_default());
        set.surface_data.is_normal_flipped = is_normal_flipped.unwrap_or(false);
        for surface in &surfaces {
            set.add_explicit_surface(surface.clone());
        }

        return set;
    }

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

    /// Returns the number of implicit surfaces.
    pub fn number_of_surfaces(&self) -> usize {
        return self._surfaces.len();
    }

    /// Returns the i-th implicit surface.
    pub fn surface_at(&self, i: usize) -> ImplicitSurface3Ptr {
        return self._surfaces[i].clone();
    }

    /// Adds an explicit surface instance.
    pub fn add_explicit_surface(&mut self, surface: Surface3Ptr) {
        self.add_surface(Arc::new(RwLock::new(SurfaceToImplicit3::new(surface, None, None))));
    }

    /// Adds an implicit surface instance.
    pub fn add_surface(&mut self, surface: ImplicitSurface3Ptr) {
        self._surfaces.push(surface.clone());
        if !surface.read().unwrap().is_bounded() {
            self._unbounded_surfaces.push(surface);
        }
        self.invalidate_bvh();
    }

    fn invalidate_bvh(&self) {
        *(self._bvh_invalidated.write().unwrap()) = true;
    }

    fn build_bvh(&self) {
        if *self._bvh_invalidated.read().unwrap() {
            let mut surfs: Vec<ImplicitSurface3Ptr> = Vec::new();
            let mut bounds: Vec<BoundingBox3D> = Vec::new();
            for i in 0..self._surfaces.len() {
                if self._surfaces[i].read().unwrap().is_bounded() {
                    surfs.push(self._surfaces[i].clone());
                    bounds.push(self._surfaces[i].read().unwrap().bounding_box());
                }
            }
            self._bvh.write().unwrap().build(&surfs, &bounds);
            *(self._bvh_invalidated.write().unwrap()) = false;
        }
    }
}

impl Surface3 for ImplicitSurfaceSet3 {
    fn closest_point_local(&self, other_point: &Vector3D) -> Vector3D {
        self.build_bvh();

        let mut distance_func = |surface: &ImplicitSurface3Ptr, pt: &Vector3D| {
            return surface.read().unwrap().closest_distance(pt);
        };

        let mut result = Vector3D::new(f64::MAX, f64::MAX, f64::MAX);
        let query_result = self._bvh.read().unwrap().nearest(other_point, &mut distance_func);
        if let Some(item) = query_result.item {
            result = item.read().unwrap().closest_point(other_point);
        }

        let mut min_dist = query_result.distance;
        for surface in &self._unbounded_surfaces {
            let pt = surface.read().unwrap().closest_point(other_point);
            let dist = pt.distance_to(*other_point);
            if dist < min_dist {
                min_dist = dist;
                result = surface.read().unwrap().closest_point(other_point);
            }
        }

        return result;
    }

    fn bounding_box_local(&self) -> BoundingBox3D {
        self.build_bvh();

        return self._bvh.read().unwrap().bounding_box();
    }

    fn closest_intersection_local(&self, ray: &Ray3D) -> SurfaceRayIntersection3 {
        self.build_bvh();

        let mut test_func = |surface: &ImplicitSurface3Ptr, ray: &Ray3D| {
            let result = surface.read().unwrap().closest_intersection(ray);
            return result.distance;
        };

        let query_result = self._bvh.read().unwrap().closest_intersection(ray, &mut test_func);
        let mut result = SurfaceRayIntersection3::new();
        result.distance = query_result.distance;
        result.is_intersecting = match query_result.item {
            None => false,
            Some(_) => true
        };
        if let Some(item) = query_result.item {
            result.point = ray.point_at(query_result.distance);
            result.normal = item.read().unwrap().closest_normal(&result.point);
        }

        for surface in &self._unbounded_surfaces {
            let local_result = surface.read().unwrap().closest_intersection(ray);
            if local_result.distance < result.distance {
                result = local_result;
            }
        }

        return result;
    }

    fn closest_normal_local(&self, other_point: &Vector3D) -> Vector3D {
        self.build_bvh();

        let mut distance_func = |surface: &ImplicitSurface3Ptr, pt: &Vector3D| {
            return surface.read().unwrap().closest_distance(pt);
        };

        let mut result = Vector3D::new(1.0, 0.0, 0.0);
        let query_result = self._bvh.read().unwrap().nearest(other_point, &mut distance_func);
        if let Some(item) = query_result.item {
            result = item.read().unwrap().closest_normal(other_point);
        }

        let mut min_dist = query_result.distance;
        for surface in &self._unbounded_surfaces {
            let pt = surface.read().unwrap().closest_point(other_point);
            let dist = pt.distance_to(*other_point);
            if dist < min_dist {
                min_dist = dist;
                result = surface.read().unwrap().closest_normal(other_point);
            }
        }

        return result;
    }

    fn intersects_local(&self, ray: &Ray3D) -> bool {
        self.build_bvh();

        let mut test_func = |surface: &ImplicitSurface3Ptr, ray: &Ray3D| {
            return surface.read().unwrap().intersects(ray);
        };

        let mut result = self._bvh.read().unwrap().intersects_ray(ray, &mut test_func);
        for surface in &self._unbounded_surfaces {
            result |= surface.read().unwrap().intersects(ray);
        }

        return result;
    }

    fn closest_distance_local(&self, other_point: &Vector3D) -> f64 {
        self.build_bvh();

        let mut distance_func = |surface: &ImplicitSurface3Ptr, pt: &Vector3D| {
            return surface.read().unwrap().closest_distance(pt);
        };

        let query_result = self._bvh.read().unwrap().nearest(other_point, &mut distance_func);

        let mut min_dist = query_result.distance;
        for surface in &self._unbounded_surfaces {
            let pt = surface.read().unwrap().closest_point(other_point);
            let dist = pt.distance_to(*other_point);
            if dist < min_dist {
                min_dist = dist;
            }
        }

        return min_dist;
    }

    fn update_query_engine(&self) {
        self.invalidate_bvh();
        self.build_bvh();
    }

    fn is_bounded(&self) -> bool {
        // All surfaces should be bounded.
        for surface in &self._surfaces {
            if !surface.read().unwrap().is_bounded() {
                return false;
            }
        }

        // Empty set is not bounded.
        return !self._surfaces.is_empty();
    }

    fn is_valid_geometry(&self) -> bool {
        // All surfaces should be valid.
        for surface in &self._surfaces {
            if !surface.read().unwrap().is_valid_geometry() {
                return false;
            }
        }

        // Empty set is not valid.
        return !self._surfaces.is_empty();
    }

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

impl ImplicitSurface3 for ImplicitSurfaceSet3 {
    fn signed_distance_local(&self, other_point: &Vector3D) -> f64 {
        let mut sdf = f64::MAX;
        for surface in &self._surfaces {
            sdf = f64::min(sdf, surface.read().unwrap().signed_distance(other_point));
        }

        return sdf;
    }

    fn is_inside_local(&self, other_point: &Vector3D) -> bool {
        for surface in &self._surfaces {
            if surface.read().unwrap().is_inside(other_point) {
                return true;
            }
        }

        return false;
    }
}

/// Shared pointer type for the ImplicitSurfaceSet3.
pub type ImplicitSurfaceSet3Ptr = Arc<RwLock<ImplicitSurfaceSet3>>;

///
/// # Front-end to create ImplicitSurfaceSet3 objects step by step.
///
pub struct Builder {
    _surfaces: Vec<ImplicitSurface3Ptr>,

    _surface_data: Surface3Data,
}

impl Builder {
    /// Returns builder with surfaces.
    pub fn with_surfaces(&mut self, surfaces: Vec<ImplicitSurface3Ptr>) -> &mut Self {
        self._surfaces = surfaces;
        return self;
    }

    /// Returns builder with explicit surfaces.
    pub fn with_explicit_surfaces(&mut self, surfaces: Vec<Surface3Ptr>) -> &mut Self {
        self._surfaces.clear();
        for surface in surfaces {
            self._surfaces.push(Arc::new(RwLock::new(SurfaceToImplicit3::new(surface, None, None))));
        }

        return self;
    }

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

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

    /// constructor
    pub fn new() -> Builder {
        return Builder {
            _surfaces: vec![],
            _surface_data: Surface3Data::new(None, None),
        };
    }
}

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