From 1ec396a2378025f5fea7adc226ffbba8dbf60f54 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 29 Jul 2022 15:33:24 +0200 Subject: [PATCH 1/5] Add `SurfaceSurfaceIntersection` --- .../src/algorithms/intersection/mod.rs | 2 +- .../intersection/surface_surface.rs | 24 +++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersection/mod.rs b/crates/fj-kernel/src/algorithms/intersection/mod.rs index c79e801bb..3eec884ec 100644 --- a/crates/fj-kernel/src/algorithms/intersection/mod.rs +++ b/crates/fj-kernel/src/algorithms/intersection/mod.rs @@ -9,5 +9,5 @@ pub use self::{ curve_edge::CurveEdgeIntersection, curve_face::{CurveFaceIntersection, CurveFaceIntersectionList}, line_segment::LineSegmentIntersection, - surface_surface::surface_surface, + surface_surface::{surface_surface, SurfaceSurfaceIntersection}, }; diff --git a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs index 5b771d384..e2b233c35 100644 --- a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs @@ -2,11 +2,21 @@ use fj_math::{Line, Point, Scalar, Vector}; use crate::objects::{Curve, Surface}; +/// The intersection between two surfaces +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct SurfaceSurfaceIntersection { + /// The intersection curves, in the coordinates of the input surfaces + pub local_intersection_curves: [Curve<2>; 2], + + /// The intersection curve, in global coordinates + pub global_intersection_curve: Curve<3>, +} + /// Test intersection between two surfaces pub fn surface_surface( a: &Surface, b: &Surface, -) -> Option<(Curve<2>, Curve<2>, Curve<3>)> { +) -> Option { // Algorithm from Real-Time Collision Detection by Christer Ericson. See // section 5.4.4, Intersection of Two Planes. // @@ -44,7 +54,10 @@ pub fn surface_surface( let curve_b = project_line_into_plane(&line, &b_parametric); let curve_global = Curve::Line(Line { origin, direction }); - Some((curve_a, curve_b, curve_global)) + Some(SurfaceSurfaceIntersection { + local_intersection_curves: [curve_a, curve_b], + global_intersection_curve: curve_global, + }) } /// A plane in parametric form @@ -134,7 +147,7 @@ mod tests { objects::{Curve, Surface}, }; - use super::surface_surface; + use super::{surface_surface, SurfaceSurfaceIntersection}; #[test] fn plane_plane() { @@ -157,7 +170,10 @@ mod tests { assert_eq!( surface_surface(&xy, &xz), - Some((expected_xy, expected_xz, expected_global)) + Some(SurfaceSurfaceIntersection { + local_intersection_curves: [expected_xy, expected_xz], + global_intersection_curve: expected_global, + }) ); } } From e81d0b9aae68cf85c40a6d95bce64ade5de02359 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 29 Jul 2022 15:37:48 +0200 Subject: [PATCH 2/5] Convert free function into associated function --- .../src/algorithms/intersection/mod.rs | 2 +- .../intersection/surface_surface.rs | 92 ++++++++++--------- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersection/mod.rs b/crates/fj-kernel/src/algorithms/intersection/mod.rs index 3eec884ec..df03b6abd 100644 --- a/crates/fj-kernel/src/algorithms/intersection/mod.rs +++ b/crates/fj-kernel/src/algorithms/intersection/mod.rs @@ -9,5 +9,5 @@ pub use self::{ curve_edge::CurveEdgeIntersection, curve_face::{CurveFaceIntersection, CurveFaceIntersectionList}, line_segment::LineSegmentIntersection, - surface_surface::{surface_surface, SurfaceSurfaceIntersection}, + surface_surface::SurfaceSurfaceIntersection, }; diff --git a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs index e2b233c35..d2dbb6468 100644 --- a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs @@ -12,52 +12,54 @@ pub struct SurfaceSurfaceIntersection { pub global_intersection_curve: Curve<3>, } -/// Test intersection between two surfaces -pub fn surface_surface( - a: &Surface, - b: &Surface, -) -> Option { - // Algorithm from Real-Time Collision Detection by Christer Ericson. See - // section 5.4.4, Intersection of Two Planes. - // - // Adaptations were made to get the intersection curves in local coordinates - // for each surface. - - let a_parametric = PlaneParametric::extract_from_surface(a); - let b_parametric = PlaneParametric::extract_from_surface(b); - - let a = PlaneConstantNormal::from_parametric_plane(&a_parametric); - let b = PlaneConstantNormal::from_parametric_plane(&b_parametric); - - let direction = a.normal.cross(&b.normal); - - let denom = direction.dot(&direction); - if denom == Scalar::ZERO { - // Comparing `denom` against zero looks fishy. It's probably better to - // compare it against an epsilon value, but I don't know how large that - // epsilon should be. +impl SurfaceSurfaceIntersection { + /// Test intersection between two surfaces + pub fn surface_surface( + a: &Surface, + b: &Surface, + ) -> Option { + // Algorithm from Real-Time Collision Detection by Christer Ericson. See + // section 5.4.4, Intersection of Two Planes. // - // I'll just leave it like that, until we had the opportunity to collect - // some experience with this code. - // - @hannobraun - return None; - } + // Adaptations were made to get the intersection curves in local + // coordinates for each surface. + + let a_parametric = PlaneParametric::extract_from_surface(a); + let b_parametric = PlaneParametric::extract_from_surface(b); + + let a = PlaneConstantNormal::from_parametric_plane(&a_parametric); + let b = PlaneConstantNormal::from_parametric_plane(&b_parametric); + + let direction = a.normal.cross(&b.normal); + + let denom = direction.dot(&direction); + if denom == Scalar::ZERO { + // Comparing `denom` against zero looks fishy. It's probably better + // to compare it against an epsilon value, but I don't know how + // large that epsilon should be. + // + // I'll just leave it like that, until we had the opportunity to + // collect some experience with this code. + // - @hannobraun + return None; + } - let origin = (b.normal * a.distance - a.normal * b.distance) - .cross(&direction) - / denom; - let origin = Point { coords: origin }; + let origin = (b.normal * a.distance - a.normal * b.distance) + .cross(&direction) + / denom; + let origin = Point { coords: origin }; - let line = Line { origin, direction }; + let line = Line { origin, direction }; - let curve_a = project_line_into_plane(&line, &a_parametric); - let curve_b = project_line_into_plane(&line, &b_parametric); - let curve_global = Curve::Line(Line { origin, direction }); + let curve_a = project_line_into_plane(&line, &a_parametric); + let curve_b = project_line_into_plane(&line, &b_parametric); + let curve_global = Curve::Line(Line { origin, direction }); - Some(SurfaceSurfaceIntersection { - local_intersection_curves: [curve_a, curve_b], - global_intersection_curve: curve_global, - }) + Some(SurfaceSurfaceIntersection { + local_intersection_curves: [curve_a, curve_b], + global_intersection_curve: curve_global, + }) + } } /// A plane in parametric form @@ -147,7 +149,7 @@ mod tests { objects::{Curve, Surface}, }; - use super::{surface_surface, SurfaceSurfaceIntersection}; + use super::SurfaceSurfaceIntersection; #[test] fn plane_plane() { @@ -155,9 +157,9 @@ mod tests { let xz = Surface::xz_plane(); // Coincident and parallel planes don't have an intersection curve. - assert_eq!(surface_surface(&xy, &xy), None); + assert_eq!(SurfaceSurfaceIntersection::surface_surface(&xy, &xy), None); assert_eq!( - surface_surface( + SurfaceSurfaceIntersection::surface_surface( &xy, &xy.transform(&Transform::translation([0., 0., 1.])) ), @@ -169,7 +171,7 @@ mod tests { let expected_global = Curve::x_axis(); assert_eq!( - surface_surface(&xy, &xz), + SurfaceSurfaceIntersection::surface_surface(&xy, &xz), Some(SurfaceSurfaceIntersection { local_intersection_curves: [expected_xy, expected_xz], global_intersection_curve: expected_global, From c79d643501121b0ebe7c86231364e46b8f8e11fe Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 29 Jul 2022 15:38:20 +0200 Subject: [PATCH 3/5] Refactor --- .../src/algorithms/intersection/surface_surface.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs index d2dbb6468..077886c5b 100644 --- a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs @@ -14,10 +14,7 @@ pub struct SurfaceSurfaceIntersection { impl SurfaceSurfaceIntersection { /// Test intersection between two surfaces - pub fn surface_surface( - a: &Surface, - b: &Surface, - ) -> Option { + pub fn surface_surface(a: &Surface, b: &Surface) -> Option { // Algorithm from Real-Time Collision Detection by Christer Ericson. See // section 5.4.4, Intersection of Two Planes. // @@ -55,7 +52,7 @@ impl SurfaceSurfaceIntersection { let curve_b = project_line_into_plane(&line, &b_parametric); let curve_global = Curve::Line(Line { origin, direction }); - Some(SurfaceSurfaceIntersection { + Some(Self { local_intersection_curves: [curve_a, curve_b], global_intersection_curve: curve_global, }) From cb6ed5e652ffe6874341a8ab35935ecefe7e038a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 29 Jul 2022 15:38:39 +0200 Subject: [PATCH 4/5] Update name of associated function --- .../src/algorithms/intersection/surface_surface.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs index 077886c5b..82759e398 100644 --- a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs @@ -14,7 +14,7 @@ pub struct SurfaceSurfaceIntersection { impl SurfaceSurfaceIntersection { /// Test intersection between two surfaces - pub fn surface_surface(a: &Surface, b: &Surface) -> Option { + pub fn compute(a: &Surface, b: &Surface) -> Option { // Algorithm from Real-Time Collision Detection by Christer Ericson. See // section 5.4.4, Intersection of Two Planes. // @@ -154,9 +154,9 @@ mod tests { let xz = Surface::xz_plane(); // Coincident and parallel planes don't have an intersection curve. - assert_eq!(SurfaceSurfaceIntersection::surface_surface(&xy, &xy), None); + assert_eq!(SurfaceSurfaceIntersection::compute(&xy, &xy), None); assert_eq!( - SurfaceSurfaceIntersection::surface_surface( + SurfaceSurfaceIntersection::compute( &xy, &xy.transform(&Transform::translation([0., 0., 1.])) ), @@ -168,7 +168,7 @@ mod tests { let expected_global = Curve::x_axis(); assert_eq!( - SurfaceSurfaceIntersection::surface_surface(&xy, &xz), + SurfaceSurfaceIntersection::compute(&xy, &xz), Some(SurfaceSurfaceIntersection { local_intersection_curves: [expected_xy, expected_xz], global_intersection_curve: expected_global, From 5bcc4a85f4cedb9403fe493b8523b88690c28250 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 29 Jul 2022 15:39:01 +0200 Subject: [PATCH 5/5] Update doc comment --- crates/fj-kernel/src/algorithms/intersection/surface_surface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs index 82759e398..820cca925 100644 --- a/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs +++ b/crates/fj-kernel/src/algorithms/intersection/surface_surface.rs @@ -13,7 +13,7 @@ pub struct SurfaceSurfaceIntersection { } impl SurfaceSurfaceIntersection { - /// Test intersection between two surfaces + /// Compute the intersection between two surfaces pub fn compute(a: &Surface, b: &Surface) -> Option { // Algorithm from Real-Time Collision Detection by Christer Ericson. See // section 5.4.4, Intersection of Two Planes.