diff --git a/Cargo.toml b/Cargo.toml index 4d82573..d5fc951 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,70 +19,30 @@ unexpected_cfgs = "warn" [workspace.lints.clippy] all = { level = "warn", priority = -1 } -await_holding_lock = "warn" -char_lit_as_u8 = "warn" -checked_conversions = "warn" -dbg_macro = "warn" -debug_assert_with_mut_call = "warn" -doc_markdown = "warn" -empty_enum = "warn" -enum_glob_use = "warn" -exit = "warn" -expl_impl_clone_on_copy = "warn" -explicit_deref_methods = "warn" -explicit_into_iter_loop = "warn" -fallible_impl_from = "warn" -filter_map_next = "warn" -flat_map_option = "warn" -float_cmp_const = "warn" -fn_params_excessive_bools = "warn" -from_iter_instead_of_collect = "warn" -if_let_mutex = "warn" -implicit_clone = "warn" -imprecise_flops = "warn" -inefficient_to_string = "warn" -invalid_upcast_comparisons = "warn" -large_digit_groups = "warn" -large_stack_arrays = "warn" -large_types_passed_by_value = "warn" -let_unit_value = "warn" -linkedlist = "warn" -lossy_float_literal = "warn" -macro_use_imports = "warn" -manual_ok_or = "warn" -map_err_ignore = "warn" -map_flatten = "warn" -map_unwrap_or = "warn" -match_on_vec_items = "warn" -match_same_arms = "warn" -match_wild_err_arm = "warn" -match_wildcard_for_single_variants = "warn" -mem_forget = "warn" -missing_enforced_import_renames = "warn" -mut_mut = "warn" -mutex_integer = "warn" -needless_borrow = "warn" -needless_continue = "warn" -needless_for_each = "warn" -option_option = "warn" -path_buf_push_overwrite = "warn" -ptr_as_ptr = "warn" -rc_mutex = "warn" -ref_option_ref = "warn" -rest_pat_in_fully_bound_structs = "warn" -same_functions_in_if_condition = "warn" -semicolon_if_nothing_returned = "warn" -single_match_else = "warn" -string_add_assign = "warn" -string_add = "warn" -string_lit_as_bytes = "warn" -string_to_string = "warn" -todo = "warn" -trait_duplication_in_bounds = "warn" -unimplemented = "warn" -unnested_or_patterns = "warn" -unused_self = "warn" -useless_transmute = "warn" -verbose_file_reads = "warn" -zero_sized_map_values = "warn" -# missing_docs_in_private_items = "warn" +pedantic = { level = "warn", priority = -1 } +nursery = { level = "warn", priority = -1 } +complexity = {level = "warn", priority = -1 } +style = { level = "warn", priority = -1 } + +significant_drop_tightening = "allow" +module_name_repetitions = "allow" +cast_sign_loss = "allow" +cast_precision_loss = "allow" +cast_possible_truncation = "allow" +missing_errors_doc = "allow" +missing_panics_doc = "allow" + +# From restriction +same_name_method = "allow" # because of rust embed, see https://github.com/pyrossh/rust-embed/issues/204 +std_instead_of_core = "warn" +clone_on_ref_ptr = "warn" +renamed_function_params = "warn" +#unseparated_literal_suffix = "warn" +redundant_type_annotations = "warn" +partial_pub_fields = "warn" +let_underscore_untyped = "warn" +let_underscore_must_use = "warn" +ref_patterns = "warn" +undocumented_unsafe_blocks = "warn" +wildcard_enum_match_arm = "warn" +suboptimal_flops = "allow" diff --git a/mesh_to_sdf/src/bvh_ext.rs b/mesh_to_sdf/src/bvh_ext.rs index b131279..f520394 100644 --- a/mesh_to_sdf/src/bvh_ext.rs +++ b/mesh_to_sdf/src/bvh_ext.rs @@ -50,7 +50,7 @@ impl AabbExt for Aabb { // Invert the signum to get the furthest vertex .map(|x| -x.signum()) // Make sure we're always on a vertex and not on a face if the point is aligned with the box - .map(|x| if x != 0.0 { x } else { 1.0 }); + .map(|x| if x == 0.0 { 1.0 } else { x }); let furthest = center + signum.component_mul(&half_size); let max_dist = (n_point - furthest).norm(); @@ -65,7 +65,7 @@ pub trait BvhDistance> { /// fn nearest_candidates(&self, origin: &V, shapes: &[Shape]) -> Vec where - Self: std::marker::Sized; + Self: core::marker::Sized; } impl> BvhDistance for Bvh { @@ -107,13 +107,14 @@ pub trait BvhTraverseDistance> { best_min_distance: &mut f32, best_max_distance: &mut f32, ) where - Self: std::marker::Sized; + Self: core::marker::Sized; } impl> BvhTraverseDistance for BvhNode { /// Traverses the [`Bvh`] recursively and returns all shapes whose [`Aabb`] countains /// a candidate shape for being the nearest to the given point. /// + #[expect(clippy::similar_names)] fn nearest_candidates_recursive( nodes: &[Self], node_index: usize, @@ -123,11 +124,11 @@ impl> BvhTraverseDistance for BvhNode best_min_distance: &mut f32, best_max_distance: &mut f32, ) { - match nodes[node_index] { - BvhNode::Node { - ref child_l_aabb, + match &nodes[node_index] { + Self::Node { + child_l_aabb, child_l_index, - ref child_r_aabb, + child_r_aabb, child_r_index, .. } => { @@ -153,7 +154,7 @@ impl> BvhTraverseDistance for BvhNode if dist_min <= *best_max_distance { Self::nearest_candidates_recursive( nodes, - index, + *index, origin, shapes, indices, @@ -163,8 +164,8 @@ impl> BvhTraverseDistance for BvhNode } } } - BvhNode::Leaf { shape_index, .. } => { - let aabb = shapes[shape_index].aabb(); + Self::Leaf { shape_index, .. } => { + let aabb = shapes[*shape_index].aabb(); let (min_dist, max_dist) = aabb.get_min_max_distances(origin); if !indices.is_empty() && max_dist < *best_min_distance { @@ -177,7 +178,7 @@ impl> BvhTraverseDistance for BvhNode *best_max_distance = best_max_distance.min(max_dist); // we reached a leaf, we add it to the list of indices since it is a potential candidate - indices.push((shape_index, min_dist)); + indices.push((*shape_index, min_dist)); } } } diff --git a/mesh_to_sdf/src/generate/generic/bvh.rs b/mesh_to_sdf/src/generate/generic/bvh.rs index ef1f8de..73e5c1f 100644 --- a/mesh_to_sdf/src/generate/generic/bvh.rs +++ b/mesh_to_sdf/src/generate/generic/bvh.rs @@ -1,6 +1,6 @@ //! Module containing the `generate_sdf_bvh` function. -use std::cmp::Ordering; +use core::cmp::Ordering; use bvh::{bounding_hierarchy::BoundingHierarchy, bvh::Bvh}; use itertools::Itertools; @@ -12,7 +12,7 @@ use crate::{bvh_ext::BvhDistance, compare_distances, geo, Point, SignMethod, Top /// Public in the crate so that the grid generation can use it. /// `RtreeBvh` uses its own version of this struct to be able to implement the `RTreeObject` trait. #[derive(Clone)] -pub(crate) struct BvhNode { +pub struct BvhNode { pub vertex_indices: (usize, usize, usize), pub node_index: usize, pub bounding_box: (V, V), @@ -49,7 +49,7 @@ impl bvh::bounding_hierarchy::BHShape for BvhNode { /// /// Returns a vector of signed distances. /// Queries outside the mesh will have a positive distance, and queries inside the mesh will have a negative distance. -pub(crate) fn generate_sdf_bvh( +pub fn generate_sdf_bvh( vertices: &[V], indices: Topology, query_points: &[V], diff --git a/mesh_to_sdf/src/generate/generic/default.rs b/mesh_to_sdf/src/generate/generic/default.rs index 2ea45f4..5eba505 100644 --- a/mesh_to_sdf/src/generate/generic/default.rs +++ b/mesh_to_sdf/src/generate/generic/default.rs @@ -8,7 +8,7 @@ use crate::{compare_distances, geo, Point, SignMethod, Topology}; /// /// Returns a vector of signed distances. /// Queries outside the mesh will have a positive distance, and queries inside the mesh will have a negative distance. -pub(crate) fn generate_sdf_default( +pub fn generate_sdf_default( vertices: &[V], indices: Topology, query_points: &[V], @@ -47,12 +47,14 @@ where match sign_method { SignMethod::Raycast => ( min_distance.min(distance), - intersection_count + ray_intersection as u32, + intersection_count + u32::from(ray_intersection), ), SignMethod::Normal => ( match compare_distances(distance, min_distance) { - std::cmp::Ordering::Less => distance, - _ => min_distance, + core::cmp::Ordering::Less => distance, + core::cmp::Ordering::Equal | core::cmp::Ordering::Greater => { + min_distance + } }, intersection_count, ), diff --git a/mesh_to_sdf/src/generate/generic/mod.rs b/mesh_to_sdf/src/generate/generic/mod.rs index 69b7e58..3a283a0 100644 --- a/mesh_to_sdf/src/generate/generic/mod.rs +++ b/mesh_to_sdf/src/generate/generic/mod.rs @@ -1,6 +1,6 @@ //! Module containing the different `generate_sdf` functions, one for each acceleration structure. -pub(crate) mod bvh; -pub(crate) mod default; -pub(crate) mod rtree; -pub(crate) mod rtree_bvh; +pub mod bvh; +pub mod default; +pub mod rtree; +pub mod rtree_bvh; diff --git a/mesh_to_sdf/src/generate/generic/rtree.rs b/mesh_to_sdf/src/generate/generic/rtree.rs index 9d97b6c..c64894e 100644 --- a/mesh_to_sdf/src/generate/generic/rtree.rs +++ b/mesh_to_sdf/src/generate/generic/rtree.rs @@ -21,7 +21,7 @@ where let x = generator(0); let y = generator(1); let z = generator(2); - PointWrapper(V::new(x, y, z)) + Self(V::new(x, y, z)) } fn nth(&self, index: usize) -> Self::Scalar { @@ -84,7 +84,7 @@ impl rstar::PointDistance for RtreeNode { /// /// This method is only compatible with normal sign method. /// If you want to use raycasting, use `AccelerationMethod::RtreeBvh` instead. -pub(crate) fn generate_sdf_rtree( +pub fn generate_sdf_rtree( vertices: &[V], indices: Topology, query_points: &[V], diff --git a/mesh_to_sdf/src/generate/grid.rs b/mesh_to_sdf/src/generate/grid.rs index c2dc127..e98a950 100644 --- a/mesh_to_sdf/src/generate/grid.rs +++ b/mesh_to_sdf/src/generate/grid.rs @@ -1,6 +1,7 @@ //! Grid generation module. -use std::{sync::atomic::AtomicU32, thread::ScopedJoinHandle}; +use core::sync::atomic::AtomicU32; +use std::thread::ScopedJoinHandle; use bvh::{bounding_hierarchy::BoundingHierarchy, bvh::Bvh}; use itertools::Itertools; @@ -26,14 +27,14 @@ struct State { impl Ord for State { /// We compare by distance first, then use cell and triangles as tie-breakers. /// Only the distance is important to reduce the number of steps. - fn cmp(&self, other: &Self) -> std::cmp::Ordering { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { compare_distances(other.distance.into_inner(), self.distance.into_inner()) .then_with(|| self.cell.cmp(&other.cell)) .then_with(|| self.triangle.cmp(&other.triangle)) } } impl PartialOrd for State { - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } @@ -91,9 +92,8 @@ where // starting the preheap computation as they both use the same rayon thread pool. // this is the only precomputation using the rayon thread pool. // If we're not in Raycast mode, we don't compute the bvh. - let mut bvh_handle = None; - if sign_method == SignMethod::Raycast { - bvh_handle = Some(scope.spawn(move || { + let bvh_handle = if sign_method == SignMethod::Raycast { + Some(scope.spawn(move || { let mut bvh_nodes = Topology::get_triangles(vertices, indices) .map(|triangle| BvhNode { vertex_indices: triangle, @@ -108,8 +108,10 @@ where let bvh = Bvh::build_par(&mut bvh_nodes); (bvh, bvh_nodes) - })); - } + })) + } else { + None + }; // prehead initialization. RwLock can be slow to create one by one. // Needed for the first step (preheap computation). @@ -300,7 +302,7 @@ where // First step done. log::info!( "[generate_grid_sdf] init steps: {} in {:.3}ms", - steps.fetch_min(0, std::sync::atomic::Ordering::SeqCst), + steps.fetch_min(0, core::sync::atomic::Ordering::SeqCst), now.elapsed().as_secs_f64() * 1000.0 ); now = web_time::Instant::now(); @@ -339,7 +341,7 @@ where // Second step done. log::info!( "[generate_grid_sdf] propagation steps: {} in {:.3}ms", - steps.fetch_min(0, std::sync::atomic::Ordering::SeqCst), + steps.fetch_min(0, core::sync::atomic::Ordering::SeqCst), now.elapsed().as_secs_f64() * 1000.0 ); now = web_time::Instant::now(); @@ -446,7 +448,7 @@ fn generate_preheap( let mut stored_distance = preheap[cell_idx].write(); if compare_distances(distance, stored_distance.1).is_lt() { // New smallest ditance: update the grid and add the cell to the heap. - steps.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + steps.fetch_add(1, core::sync::atomic::Ordering::Relaxed); *stored_distance = (triangle, distance); } } @@ -476,6 +478,7 @@ fn generate_heap( *distances[cell_idx].write() = distance; State { distance: NotNan::new(distance) + // SAFETY: f32::MAX is not Nan. .unwrap_or(unsafe { NotNan::new_unchecked(f32::MAX) }), triangle, @@ -498,13 +501,14 @@ fn propagate_heap( steps: &AtomicU32, ) { while let Some(State { triangle, cell, .. }) = heap.pop() { - steps.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + steps.fetch_add(1, core::sync::atomic::Ordering::Relaxed); let a = &vertices[triangle.0]; let b = &vertices[triangle.1]; let c = &vertices[triangle.2]; // Compute neighbours around the cell in the three directions. // Discard neighbours that are outside the grid. + #[expect(clippy::cast_possible_wrap)] let neighbours = itertools::iproduct!(-1..=1, -1..=1, -1..=1) .map(|v| { ( @@ -541,6 +545,7 @@ fn propagate_heap( *stored_distance = distance; let state = State { distance: NotNan::new(distance) + // SAFETY: f32::MAX is not Nan. .unwrap_or(unsafe { NotNan::new_unchecked(f32::MAX) }), triangle, cell: neighbour_cell, @@ -586,7 +591,7 @@ fn compute_raycasts( let candidates = bvh.traverse(&ray, bvh_nodes); raycasts_done.fetch_add( candidates.len() as u32, - std::sync::atomic::Ordering::Relaxed, + core::sync::atomic::Ordering::Relaxed, ); for candidate in candidates { let a = &vertices[candidate.vertex_indices.0]; @@ -608,7 +613,7 @@ fn compute_raycasts( cell[direction_index] = index; let cell_idx = grid.get_cell_idx(&cell); intersections[cell_idx][direction_index] - .fetch_add(1, std::sync::atomic::Ordering::Relaxed); + .fetch_add(1, core::sync::atomic::Ordering::Relaxed); } } } @@ -621,9 +626,9 @@ fn compute_raycasts( // This helps when the mesh is not watertight // and to compensate the discrete nature of the grid. let inter = [ - intersections[i][0].load(std::sync::atomic::Ordering::SeqCst), - intersections[i][1].load(std::sync::atomic::Ordering::SeqCst), - intersections[i][2].load(std::sync::atomic::Ordering::SeqCst), + intersections[i][0].load(core::sync::atomic::Ordering::SeqCst), + intersections[i][1].load(core::sync::atomic::Ordering::SeqCst), + intersections[i][2].load(core::sync::atomic::Ordering::SeqCst), ]; match (inter[0] % 2, inter[1] % 2, inter[2] % 2) { // if at least two are odd, the cell is deeemed inside. @@ -633,7 +638,7 @@ fn compute_raycasts( } } - raycasts_done.load(std::sync::atomic::Ordering::SeqCst) + raycasts_done.load(core::sync::atomic::Ordering::SeqCst) } /// Generate raycasts for the sign raycast method in a grid. diff --git a/mesh_to_sdf/src/generate/mod.rs b/mesh_to_sdf/src/generate/mod.rs index 321bd1b..abe528a 100644 --- a/mesh_to_sdf/src/generate/mod.rs +++ b/mesh_to_sdf/src/generate/mod.rs @@ -1,4 +1,4 @@ //! Module for generating SDFs from meshes. -pub(crate) mod generic; -pub(crate) mod grid; +pub mod generic; +pub mod grid; diff --git a/mesh_to_sdf/src/geo.rs b/mesh_to_sdf/src/geo.rs index e434adb..a1ea44e 100644 --- a/mesh_to_sdf/src/geo.rs +++ b/mesh_to_sdf/src/geo.rs @@ -2,6 +2,8 @@ use crate::point::Point; /// Compute the bounding box of a triangle. pub fn triangle_bounding_box(a: &V, b: &V, c: &V) -> (V, V) { + const EPSILONF: f32 = 0.0001; + let min = V::new( f32::min(a.x(), f32::min(b.x(), c.x())), f32::min(a.y(), f32::min(b.y(), c.y())), @@ -15,7 +17,6 @@ pub fn triangle_bounding_box(a: &V, b: &V, c: &V) -> (V, V) { // We add a small epsilon to the max and subtract a small epsilon from the min to avoid // floating point errors in the bvh aabb intersection tests and make sure the aabb has a volume. - const EPSILONF: f32 = 0.0001; let epsilon = V::new(EPSILONF, EPSILONF, EPSILONF); (min.sub(&epsilon), max.add(&epsilon)) } @@ -65,6 +66,7 @@ fn triangle_normal(a: &V, b: &V, c: &V) -> V { /// Project a point onto a triangle. /// Adapted from Embree. /// +#[expect(clippy::many_single_char_names)] fn closest_point_triangle(p: &V, a: &V, b: &V, c: &V) -> V { // Add safety checks for degenerate triangles #[allow(clippy::match_same_arms)] diff --git a/mesh_to_sdf/src/grid.rs b/mesh_to_sdf/src/grid.rs index 517a014..a3d2e83 100644 --- a/mesh_to_sdf/src/grid.rs +++ b/mesh_to_sdf/src/grid.rs @@ -24,7 +24,7 @@ pub enum SnapResult { /// Note that if you want to sample x in 0 1 2 .. 10, you need 11 cells in this direction and not 10. /// - `cell_size` can be different in each direction and even negative. /// - `cell_count` can be different in each direction -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(bound = "V: Serialize + DeserializeOwned"))] pub struct Grid { @@ -40,7 +40,7 @@ impl Grid { /// Create a new grid. /// - `first_cell` is the center of the first cell. /// - `cell_size` is the size of a cell. A cell goes from `center - cell_size / 2` to `center + cell_size / 2`. - pub fn new(first_cell: V, cell_size: V, cell_count: [usize; 3]) -> Self { + pub const fn new(first_cell: V, cell_size: V, cell_count: [usize; 3]) -> Self { Self { first_cell, cell_size, @@ -74,7 +74,7 @@ impl Grid { } /// Get the center of the first cell. - pub fn get_first_cell(&self) -> V { + pub const fn get_first_cell(&self) -> V { self.first_cell } @@ -88,17 +88,17 @@ impl Grid { } /// Get the size of a cell. - pub fn get_cell_size(&self) -> V { + pub const fn get_cell_size(&self) -> V { self.cell_size } /// Get the number of cells in each direction. - pub fn get_cell_count(&self) -> [usize; 3] { + pub const fn get_cell_count(&self) -> [usize; 3] { self.cell_count } /// Get the total of cells. - pub fn get_total_cell_count(&self) -> usize { + pub const fn get_total_cell_count(&self) -> usize { self.cell_count[0] * self.cell_count[1] * self.cell_count[2] } @@ -119,12 +119,12 @@ impl Grid { } /// Get the index of a cell in a grid. - pub fn get_cell_idx(&self, cell: &[usize; 3]) -> usize { + pub const fn get_cell_idx(&self, cell: &[usize; 3]) -> usize { cell[2] + cell[1] * self.cell_count[2] + cell[0] * self.cell_count[1] * self.cell_count[2] } /// Get the integer coordinates of a cell index in a grid. - pub fn get_cell_integer_coordinates(&self, cell_idx: usize) -> [usize; 3] { + pub const fn get_cell_integer_coordinates(&self, cell_idx: usize) -> [usize; 3] { let z = cell_idx % self.cell_count[2]; let y = (cell_idx / self.cell_count[2]) % self.cell_count[1]; let x = cell_idx / (self.cell_count[1] * self.cell_count[2]); @@ -153,6 +153,7 @@ impl Grid { cell.z().floor() as isize, ]; + #[expect(clippy::cast_possible_wrap)] let ires = [ cell[0].clamp(0, self.cell_count[0] as isize - 1), cell[1].clamp(0, self.cell_count[1] as isize - 1), @@ -161,10 +162,10 @@ impl Grid { let res = [ires[0] as usize, ires[1] as usize, ires[2] as usize]; - if ires != cell { - SnapResult::Outside(res) - } else { + if ires == cell { SnapResult::Inside(res) + } else { + SnapResult::Outside(res) } } diff --git a/mesh_to_sdf/src/lib.rs b/mesh_to_sdf/src/lib.rs index f6a87ba..4d420b5 100644 --- a/mesh_to_sdf/src/lib.rs +++ b/mesh_to_sdf/src/lib.rs @@ -175,7 +175,7 @@ where /// Returns an iterator of tuples of 3 indices representing a triangle. fn get_triangles( vertices: &'a [V], - indices: Topology<'a, I>, + indices: Self, ) -> Box + Send + 'a> where V: Point, @@ -240,7 +240,7 @@ pub enum AccelerationMethod { } /// Compare two signed distances, taking into account floating point errors and signs. -fn compare_distances(a: f32, b: f32) -> std::cmp::Ordering { +fn compare_distances(a: f32, b: f32) -> core::cmp::Ordering { // for a point to be inside, it has to be inside all normals of nearest triangles. // if one distance is positive, then the point is outside. // this check is sensible to floating point errors though @@ -249,8 +249,8 @@ fn compare_distances(a: f32, b: f32) -> std::cmp::Ordering { if float_cmp::approx_eq!(f32, a.abs(), b.abs(), ulps = 2, epsilon = 1e-6) { // they are equals: return the one with the smallest distance, privileging positive distances. match (a.is_sign_negative(), b.is_sign_negative()) { - (true, false) => std::cmp::Ordering::Greater, - (false, true) => std::cmp::Ordering::Less, + (true, false) => core::cmp::Ordering::Greater, + (false, true) => core::cmp::Ordering::Less, _ => a.abs().partial_cmp(&b.abs()).unwrap(), } } else { diff --git a/mesh_to_sdf/src/point.rs b/mesh_to_sdf/src/point.rs index 6818ba0..d949720 100644 --- a/mesh_to_sdf/src/point.rs +++ b/mesh_to_sdf/src/point.rs @@ -18,7 +18,7 @@ mod impl_nalgebra; /// While everything could be done with new/x/y/z only, /// the other methods are provided for optimization purposes, /// relying on the client math library to provide optimized implementations when possible. -pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { +pub trait Point: Sized + Copy + Sync + Send + core::fmt::Debug + PartialEq { /// If the `serde` feature is enabled, the Point should be serializable and deserializable. /// You should set Serde to Self: /// ```ignore @@ -41,13 +41,17 @@ pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { type Serde: Serialize + DeserializeOwned; /// Create a new point. + #[must_use] fn new(x: f32, y: f32, z: f32) -> Self; /// Get the x coordinate. + #[must_use] fn x(&self) -> f32; /// Get the y coordinate. + #[must_use] fn y(&self) -> f32; /// Get the z coordinate. + #[must_use] fn z(&self) -> f32; /// Get the x coordinate mutably. @@ -58,6 +62,7 @@ pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { fn z_mut(&mut self) -> &mut f32; /// Get the coordinate at index `i`. + #[must_use] fn get(&self, i: usize) -> f32 { match i { 0 => self.x(), @@ -72,6 +77,7 @@ pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { // but a default implementation is provided that uses new/x/y/z as a fallback. /// Add two points. + #[must_use] fn add(&self, other: &Self) -> Self { Self::new( self.x() + other.x(), @@ -80,6 +86,7 @@ pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { ) } /// Subtract two points. + #[must_use] fn sub(&self, other: &Self) -> Self { Self::new( self.x() - other.x(), @@ -88,10 +95,12 @@ pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { ) } /// Dot product of two points. + #[must_use] fn dot(&self, other: &Self) -> f32 { self.x() * other.x() + self.y() * other.y() + self.z() * other.z() } /// Cross product of two points. + #[must_use] fn cross(&self, other: &Self) -> Self { Self::new( self.y() * other.z() - self.z() * other.y(), @@ -100,24 +109,29 @@ pub trait Point: Sized + Copy + Sync + Send + std::fmt::Debug + PartialEq { ) } /// Length of the point. + #[must_use] fn length(&self) -> f32 { self.dot(self).sqrt() } /// Distance between two points. + #[must_use] fn dist(&self, other: &Self) -> f32 { self.sub(other).length() } /// Distance squared between two points. + #[must_use] fn dist2(&self, other: &Self) -> f32 { let diff = self.sub(other); diff.dot(&diff) } /// Multiply a point by a scalar. + #[must_use] fn fmul(&self, other: f32) -> Self { Self::new(self.x() * other, self.y() * other, self.z() * other) } /// Divide two points by components. + #[must_use] fn comp_div(&self, other: &Self) -> Self { Self::new( self.x() / other.x(), diff --git a/mesh_to_sdf/src/point/impl_nalgebra.rs b/mesh_to_sdf/src/point/impl_nalgebra.rs index 0eef148..f60a4a1 100644 --- a/mesh_to_sdf/src/point/impl_nalgebra.rs +++ b/mesh_to_sdf/src/point/impl_nalgebra.rs @@ -6,7 +6,7 @@ impl Point for nalgebra::Point3 { /// Create a new point. fn new(x: f32, y: f32, z: f32) -> Self { - nalgebra::Point3::new(x, y, z) + Self::new(x, y, z) } /// Get the x coordinate. @@ -43,7 +43,7 @@ impl Point for nalgebra::Vector3 { /// Create a new point. fn new(x: f32, y: f32, z: f32) -> Self { - nalgebra::Vector3::new(x, y, z) + Self::new(x, y, z) } /// Get the x coordinate.