Skip to content

Commit

Permalink
add distance
Browse files Browse the repository at this point in the history
  • Loading branch information
besok committed Jan 9, 2025
1 parent 745deb8 commit 9472b55
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 14 deletions.
18 changes: 18 additions & 0 deletions docs/src/distance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Distance

Calculate the distance in 3D space.

It can be used to calculate the distance between:

- two vertices
- a vertex and a mesh
- two meshes

The running example can be found
in the <a href="https://github.com/besok/tessellate/tree/main/examples/distance" target="_blank">repository</a>

## Notes

The distance is calculated using the Euclidean distance formula.
The meshes must be watertight and closed.
It uses existing KDTree implementation with vertices so the precision is limited to the vertices.
2 changes: 2 additions & 0 deletions examples/distance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This example demonstrates how to measure the distance between two objects.

The distance can be calculated between two points, surface and vertex or two surfaces.

## How to Run

To run this example, use the following command:
Expand Down
16 changes: 8 additions & 8 deletions examples/distance/main.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
use glam::{Mat4, Vec3};
use tessellate::gpu::options::{CameraOptions, GpuOptions, LightOptions};
use tessellate::mesh::distance::{distance_between_surfaces, distance_to_surface};
use tessellate::mesh::shape::pyramid::Pyramid;
use tessellate::mesh::shape::torus::Torus;
use tessellate::mesh::transform::Transform;
use tessellate::mesh::HasMesh;
use tessellate::{v, TessResult};
use tessellate::mesh::distance::{distance_between_surfaces, distance_to_surface};
use tessellate::{gpu, v, TessResult};

fn main() -> TessResult<()> {
let torus = Torus::default();
let mut pyramid = Pyramid::default();
pyramid.transform(Mat4::from_translation(Vec3::new(5.0, 5.0, 5.0)))?;
pyramid.transform(Mat4::from_translation(Vec3::new(2.0, 2.0, 2.0)))?;

let torus_centroid = torus.centroid()?;
let pyramid_centroid = pyramid.centroid()?;


println!("Distances");
println!(" Centroids = {}", torus_centroid.distance(&pyramid_centroid));
println!(" Torus centroid and pyramid = {}",distance_to_surface(&torus_centroid, &pyramid)? );
println!(" Pyramid centroid and torus = {}",distance_to_surface(&pyramid_centroid, &torus)? );
println!(" Surfaces = {}",distance_between_surfaces(&pyramid, &torus)? );
println!(" Torus centroid and pyramid = {}", distance_to_surface(&torus_centroid, &pyramid)?);
println!(" Pyramid centroid and torus = {}", distance_to_surface(&pyramid_centroid, &torus)?);
println!(" Surfaces = {}", distance_between_surfaces(&pyramid, &torus)?);

Ok(())
Ok(gpu::visualize(vec![torus.mesh().clone(), pyramid.mesh().clone()], GpuOptions::default())?)
}
2 changes: 1 addition & 1 deletion src/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ impl Mesh {
&self.faces
}

pub fn props(&self) -> properties::MeshProperties {
pub fn properties(&self) -> properties::MeshProperties {
properties::MeshProperties::new(self)
}

Expand Down
52 changes: 49 additions & 3 deletions src/mesh/distance.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,56 @@
use super::{Mesh, MeshResult};
use crate::mesh::parts::vertex::Vertex;

/// Calculate the distance from a vertex to the surface of a mesh
///
/// Note1: The mesh must be watertight and closed.
/// Note2: It uses existing KDTree implementation with vertices so the precision is limited to the vertices.
/// # Arguments
///
/// * `lhs` - A reference to the `Vertex` from which the distance is measured
/// * `rhs` - A reference to the `Mesh` to which the distance is measured
///
/// # Returns
///
/// * `MeshResult<f32>` - A result containing the distance or an error
pub fn distance_to_surface(lhs: &Vertex, rhs: &Mesh) -> MeshResult<f32> {
Ok(1.0)
}
if !rhs.properties().is_watertight() {
return Err("Mesh must be watertight and closed".into());
}

rhs.query()
.try_kd_tree(None)?
.nearest_neighbors(lhs, None)
.min()
.map(|n| n.distance)
.ok_or("No nearest neighbor found".into())
}
/// Calculate the distance between the surfaces of two meshes
///
/// Note1: Both meshes must be watertight and closed.
/// Note2: It uses existing KDTree implementation with vertices so the precision is limited to the vertices.
///
/// # Arguments
///
/// * `lhs` - A reference to the first `Mesh`
/// * `rhs` - A reference to the second `Mesh`
///
/// # Returns
///
/// * `MeshResult<f32>` - A result containing the distance or an error
pub fn distance_between_surfaces(lhs: &Mesh, rhs: &Mesh) -> MeshResult<f32> {
Ok(1.0)
if !rhs.properties().is_watertight() || !lhs.properties().is_watertight() {
return Err("Mesh must be watertight and closed".into());
}

let rhs_tree = rhs.query().try_kd_tree(None)?;

lhs.vertices()
.iter()
.map(|v| rhs_tree.nearest_neighbors(v, None).min())
.flatten()
.min()
.map(|n| n.distance)
.ok_or("No nearest neighbor found".into())
}
4 changes: 2 additions & 2 deletions src/mesh/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use std::collections::{HashMap, HashSet};
///
/// let pyramid = Pyramid::default();
///
/// assert!(&pyramid.props().is_manifold());
/// assert!(&pyramid.props().is_watertight());
/// assert!(&pyramid.properties().is_manifold());
/// assert!(&pyramid.properties().is_watertight());
/// ```
pub struct MeshProperties<'a> {
mesh: &'a Mesh,
Expand Down

0 comments on commit 9472b55

Please sign in to comment.