From e4da3b2baad33c270cf251deb99b2403028fab95 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 10:23:03 +0200 Subject: [PATCH 1/7] Add `BoundingVolume` trait --- crates/fj-core/src/algorithms/bounding_volume/mod.rs | 11 +++++++++++ crates/fj-core/src/algorithms/mod.rs | 1 + 2 files changed, 12 insertions(+) create mode 100644 crates/fj-core/src/algorithms/bounding_volume/mod.rs diff --git a/crates/fj-core/src/algorithms/bounding_volume/mod.rs b/crates/fj-core/src/algorithms/bounding_volume/mod.rs new file mode 100644 index 000000000..040bab585 --- /dev/null +++ b/crates/fj-core/src/algorithms/bounding_volume/mod.rs @@ -0,0 +1,11 @@ +//! Compute a bounding volume for an object + +use fj_math::Aabb; + +/// Compute a bounding volume for an object +pub trait BoundingVolume { + /// Compute an axis-aligned bounding box (AABB) + /// + /// Return `None`, if no AABB can be computed (if the object is empty). + fn aabb(&self) -> Option>; +} diff --git a/crates/fj-core/src/algorithms/mod.rs b/crates/fj-core/src/algorithms/mod.rs index 1e94f868b..2786c3f95 100644 --- a/crates/fj-core/src/algorithms/mod.rs +++ b/crates/fj-core/src/algorithms/mod.rs @@ -4,6 +4,7 @@ //! on their respective purpose. pub mod approx; +pub mod bounding_volume; pub mod intersect; pub mod reverse; pub mod sweep; From 9f367145b0b904fb8f18b549cf70782d65f248e1 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 10:31:03 +0200 Subject: [PATCH 2/7] Implement `BoundingVolume` for `HalfEdge` --- .../fj-core/src/algorithms/bounding_volume/edge.rs | 13 +++++++++++++ .../fj-core/src/algorithms/bounding_volume/mod.rs | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 crates/fj-core/src/algorithms/bounding_volume/edge.rs diff --git a/crates/fj-core/src/algorithms/bounding_volume/edge.rs b/crates/fj-core/src/algorithms/bounding_volume/edge.rs new file mode 100644 index 000000000..54d044ff8 --- /dev/null +++ b/crates/fj-core/src/algorithms/bounding_volume/edge.rs @@ -0,0 +1,13 @@ +use fj_math::Aabb; + +use crate::objects::HalfEdge; + +impl super::BoundingVolume<2> for HalfEdge { + fn aabb(&self) -> Option> { + let points = self.boundary().map(|point_curve| { + self.curve().point_from_path_coords(point_curve) + }); + + Some(Aabb::<2>::from_points(points)) + } +} diff --git a/crates/fj-core/src/algorithms/bounding_volume/mod.rs b/crates/fj-core/src/algorithms/bounding_volume/mod.rs index 040bab585..ac50ab85d 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/mod.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/mod.rs @@ -1,5 +1,7 @@ //! Compute a bounding volume for an object +mod edge; + use fj_math::Aabb; /// Compute a bounding volume for an object From 6b7f8400e48f4df4bf3f72f06dcb0eb6a4faa010 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 10:52:01 +0200 Subject: [PATCH 3/7] Implement `BoundingVolume` for `Cycle` --- .../src/algorithms/bounding_volume/cycle.rs | 18 ++++++++++++++++++ .../src/algorithms/bounding_volume/mod.rs | 1 + 2 files changed, 19 insertions(+) create mode 100644 crates/fj-core/src/algorithms/bounding_volume/cycle.rs diff --git a/crates/fj-core/src/algorithms/bounding_volume/cycle.rs b/crates/fj-core/src/algorithms/bounding_volume/cycle.rs new file mode 100644 index 000000000..c598668f8 --- /dev/null +++ b/crates/fj-core/src/algorithms/bounding_volume/cycle.rs @@ -0,0 +1,18 @@ +use fj_math::Aabb; + +use crate::objects::Cycle; + +impl super::BoundingVolume<2> for Cycle { + fn aabb(&self) -> Option> { + let mut aabb: Option> = None; + + for half_edge in self.half_edges() { + let new_aabb = half_edge + .aabb() + .expect("`HalfEdge` can always compute AABB"); + aabb = Some(aabb.map_or(new_aabb, |aabb| aabb.merged(&new_aabb))); + } + + aabb + } +} diff --git a/crates/fj-core/src/algorithms/bounding_volume/mod.rs b/crates/fj-core/src/algorithms/bounding_volume/mod.rs index ac50ab85d..fa7c1698a 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/mod.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/mod.rs @@ -1,5 +1,6 @@ //! Compute a bounding volume for an object +mod cycle; mod edge; use fj_math::Aabb; From 4aadcf2455dc771336c72d2cc493bd5490417fbc Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 11:00:12 +0200 Subject: [PATCH 4/7] Implement `BoundingVolume` for `Face` --- .../src/algorithms/bounding_volume/face.rs | 24 +++++++++++++++++++ .../src/algorithms/bounding_volume/mod.rs | 1 + 2 files changed, 25 insertions(+) create mode 100644 crates/fj-core/src/algorithms/bounding_volume/face.rs diff --git a/crates/fj-core/src/algorithms/bounding_volume/face.rs b/crates/fj-core/src/algorithms/bounding_volume/face.rs new file mode 100644 index 000000000..8926680ac --- /dev/null +++ b/crates/fj-core/src/algorithms/bounding_volume/face.rs @@ -0,0 +1,24 @@ +use fj_math::Aabb; + +use crate::{geometry::curve::GlobalPath, objects::Face}; + +impl super::BoundingVolume<3> for Face { + fn aabb(&self) -> Option> { + self.exterior().aabb().map(|aabb2| { + let surface = self.surface().geometry(); + + match surface.u { + GlobalPath::Circle(_) => { + // I don't currently have an example model to test this + // with. This should change soon, and then this will panic + // and can be addressed. + todo!("Computing AABB of curved face is not supported yet") + } + GlobalPath::Line(_) => Aabb { + min: surface.point_from_surface_coords(aabb2.min), + max: surface.point_from_surface_coords(aabb2.max), + }, + } + }) + } +} diff --git a/crates/fj-core/src/algorithms/bounding_volume/mod.rs b/crates/fj-core/src/algorithms/bounding_volume/mod.rs index fa7c1698a..c368d4c29 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/mod.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/mod.rs @@ -2,6 +2,7 @@ mod cycle; mod edge; +mod face; use fj_math::Aabb; From 2bb34b67ac87fc93877f1714e6d8f1ec0261830d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 11:09:08 +0200 Subject: [PATCH 5/7] Implement `BoundingVolume` for `Shell` --- .../src/algorithms/bounding_volume/mod.rs | 1 + .../src/algorithms/bounding_volume/shell.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 crates/fj-core/src/algorithms/bounding_volume/shell.rs diff --git a/crates/fj-core/src/algorithms/bounding_volume/mod.rs b/crates/fj-core/src/algorithms/bounding_volume/mod.rs index c368d4c29..4f11a0171 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/mod.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/mod.rs @@ -3,6 +3,7 @@ mod cycle; mod edge; mod face; +mod shell; use fj_math::Aabb; diff --git a/crates/fj-core/src/algorithms/bounding_volume/shell.rs b/crates/fj-core/src/algorithms/bounding_volume/shell.rs new file mode 100644 index 000000000..0d889ffae --- /dev/null +++ b/crates/fj-core/src/algorithms/bounding_volume/shell.rs @@ -0,0 +1,19 @@ +use fj_math::Aabb; + +use crate::objects::Shell; + +impl super::BoundingVolume<3> for Shell { + fn aabb(&self) -> Option> { + let mut aabb: Option> = None; + + for face in self.faces() { + let new_aabb = face.aabb(); + aabb = aabb.map_or(new_aabb, |aabb| match new_aabb { + Some(new_aabb) => Some(aabb.merged(&new_aabb)), + None => Some(aabb), + }); + } + + aabb + } +} From 363b6d25b7d0211cd86b79b4f26e2c28e0cfad8b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 11:10:22 +0200 Subject: [PATCH 6/7] Implement `BoundingVolume` for `Solid` --- .../src/algorithms/bounding_volume/mod.rs | 1 + .../src/algorithms/bounding_volume/solid.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 crates/fj-core/src/algorithms/bounding_volume/solid.rs diff --git a/crates/fj-core/src/algorithms/bounding_volume/mod.rs b/crates/fj-core/src/algorithms/bounding_volume/mod.rs index 4f11a0171..34372592c 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/mod.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/mod.rs @@ -4,6 +4,7 @@ mod cycle; mod edge; mod face; mod shell; +mod solid; use fj_math::Aabb; diff --git a/crates/fj-core/src/algorithms/bounding_volume/solid.rs b/crates/fj-core/src/algorithms/bounding_volume/solid.rs new file mode 100644 index 000000000..4c6b5a006 --- /dev/null +++ b/crates/fj-core/src/algorithms/bounding_volume/solid.rs @@ -0,0 +1,19 @@ +use fj_math::Aabb; + +use crate::objects::Solid; + +impl super::BoundingVolume<3> for Solid { + fn aabb(&self) -> Option> { + let mut aabb: Option> = None; + + for shell in self.shells() { + let new_aabb = shell.aabb(); + aabb = aabb.map_or(new_aabb, |aabb| match new_aabb { + Some(new_aabb) => Some(aabb.merged(&new_aabb)), + None => Some(aabb), + }); + } + + aabb + } +} From d720fbbbde64a3e5558b9f62bf71daf857fb5864 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 12 Jun 2023 11:20:27 +0200 Subject: [PATCH 7/7] Compute AABB from boundary representation This is required for computing the tolerance automatically, as the AABB is required for that. With the previous approach of computing the AABB from the mesh, we would have needed the tolerance for the mesh and the mesh for the AABB, forming a circular dependency. --- crates/fj/src/handle_model.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/fj/src/handle_model.rs b/crates/fj/src/handle_model.rs index be9ccbbbc..66818a985 100644 --- a/crates/fj/src/handle_model.rs +++ b/crates/fj/src/handle_model.rs @@ -1,8 +1,11 @@ use std::ops::Deref; -use fj_core::algorithms::{approx::Tolerance, triangulate::Triangulate}; +use fj_core::algorithms::{ + approx::Tolerance, bounding_volume::BoundingVolume, + triangulate::Triangulate, +}; use fj_interop::model::Model; -use fj_math::Aabb; +use fj_math::{Aabb, Point}; use crate::Args; @@ -20,7 +23,12 @@ pub fn handle_model( ) -> Result where for<'r> (&'r M, Tolerance): Triangulate, + M: BoundingVolume<3>, { + let aabb = model.aabb().unwrap_or(Aabb { + min: Point::origin(), + max: Point::origin(), + }); let mesh = (model.deref(), tolerance.into()).triangulate(); let args = Args::parse(); @@ -29,7 +37,6 @@ where return Ok(()); } - let aabb = Aabb::<3>::from_points(mesh.vertices()); let model = Model { mesh, aabb }; crate::window::display(model, false)?;