Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up intersection code #905

Merged
merged 8 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions crates/fj-kernel/src/algorithms/intersection/curve_edge.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use fj_math::{Point, Segment};

use crate::objects::{CurveKind, Edge};
use crate::objects::{Curve, CurveKind, Edge};

use super::LineSegmentIntersection;

/// The intersection between a curve and an [`Edge`], in curve coordinates
/// The intersection between a [`Curve`] and an [`Edge`], in curve coordinates
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum CurveEdgeIntersection {
/// The curve and edge intersect at a point
Expand All @@ -26,10 +26,10 @@ impl CurveEdgeIntersection {
/// # Panics
///
/// Currently, only intersections between lines and line segments can be
/// computed. Panics, if a different type of curve or [`Edge`] is
/// computed. Panics, if a different type of [`Curve`] or [`Edge`] is
/// passed.
pub fn compute(curve: &CurveKind<2>, edge: &Edge) -> Option<Self> {
let curve_as_line = match curve {
pub fn compute(curve: &Curve, edge: &Edge) -> Option<Self> {
let curve_as_line = match curve.kind() {
CurveKind::Line(line) => line,
_ => todo!("Curve-edge intersection only supports lines"),
};
Expand Down Expand Up @@ -87,7 +87,7 @@ mod tests {
let edge = Edge::build()
.line_segment_from_points(&surface, [[1., -1.], [1., 1.]]);

let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge);
let intersection = CurveEdgeIntersection::compute(&curve, &edge);

assert_eq!(
intersection,
Expand All @@ -104,7 +104,7 @@ mod tests {
let edge = Edge::build()
.line_segment_from_points(&surface, [[-1., -1.], [-1., 1.]]);

let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge);
let intersection = CurveEdgeIntersection::compute(&curve, &edge);

assert_eq!(
intersection,
Expand All @@ -121,7 +121,7 @@ mod tests {
let edge = Edge::build()
.line_segment_from_points(&surface, [[-1., -1.], [1., -1.]]);

let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge);
let intersection = CurveEdgeIntersection::compute(&curve, &edge);

assert!(intersection.is_none());
}
Expand All @@ -133,7 +133,7 @@ mod tests {
let edge = Edge::build()
.line_segment_from_points(&surface, [[-1., 0.], [1., 0.]]);

let intersection = CurveEdgeIntersection::compute(curve.kind(), &edge);
let intersection = CurveEdgeIntersection::compute(&curve, &edge);

assert_eq!(
intersection,
Expand Down
21 changes: 9 additions & 12 deletions crates/fj-kernel/src/algorithms/intersection/curve_face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use fj_math::Point;

use crate::{
algorithms::intersection::CurveEdgeIntersection,
objects::{CurveKind, Face},
objects::{Curve, Face},
};

/// The intersections between a curve and a [`Face`], in curve coordinates
/// The intersections between a [`Curve`] and a [`Face`], in curve coordinates
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct CurveFaceIntersectionList {
intervals: Vec<CurveFaceIntersection>,
Expand All @@ -27,8 +27,8 @@ impl CurveFaceIntersectionList {
Self { intervals }
}

/// Compute the intersections between a curve and a [`Face`]
pub fn compute(curve: &CurveKind<2>, face: &Face) -> Self {
/// Compute the intersections between a [`Curve`] and a [`Face`]
pub fn compute(curve: &Curve, face: &Face) -> Self {
let edges = face.all_cycles().flat_map(|cycle| {
let edges: Vec<_> = cycle.edges().cloned().collect();
edges
Expand Down Expand Up @@ -140,18 +140,16 @@ pub type CurveFaceIntersection = [Point<1>; 2];

#[cfg(test)]
mod tests {
use fj_math::{Line, Point, Vector};

use crate::objects::{CurveKind, Face, Surface};
use crate::objects::{Curve, Face, Surface};

use super::CurveFaceIntersectionList;

#[test]
fn compute() {
let curve = CurveKind::Line(Line {
origin: Point::from([-3., 0.]),
direction: Vector::from([1., 0.]),
});
let surface = Surface::xy_plane();

let curve =
Curve::build(surface).line_from_points([[-3., 0.], [-2., 0.]]);

#[rustfmt::skip]
let exterior = [
Expand All @@ -168,7 +166,6 @@ mod tests {
[-1., 1.],
];

let surface = Surface::xy_plane();
let face = Face::build(surface)
.polygon_from_points(exterior)
.with_hole(interior);
Expand Down
47 changes: 21 additions & 26 deletions crates/fj-kernel/src/algorithms/intersection/surface_surface.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
use fj_math::{Line, Point, Scalar, Vector};

use crate::objects::{CurveKind, Surface};
use crate::objects::{Curve, CurveKind, GlobalCurve, 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: [CurveKind<2>; 2],

/// The intersection curve, in global coordinates
pub global_intersection_curve: CurveKind<3>,
/// The intersection curves
pub intersection_curves: [Curve; 2],
}

impl SurfaceSurfaceIntersection {
/// Compute the intersection between two surfaces
pub fn compute(a: &Surface, b: &Surface) -> Option<Self> {
pub fn compute(surfaces: [&Surface; 2]) -> Option<Self> {
// 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 planes_parametric =
surfaces.map(PlaneParametric::extract_from_surface);
let [a, b] = planes_parametric
.map(|plane| PlaneConstantNormal::from_parametric_plane(&plane));

let direction = a.normal.cross(&b.normal);

Expand All @@ -48,18 +44,21 @@ impl SurfaceSurfaceIntersection {

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 = CurveKind::Line(Line { origin, direction });
let curves = planes_parametric.map(|plane| {
let local = project_line_into_plane(&line, &plane);
let global = CurveKind::Line(Line { origin, direction });

Curve::new(local, GlobalCurve::from_kind(global))
});

Some(Self {
local_intersection_curves: [curve_a, curve_b],
global_intersection_curve: curve_global,
intersection_curves: curves,
})
}
}

/// A plane in parametric form
#[derive(Clone, Copy)]
struct PlaneParametric {
pub origin: Point<3>,
pub u: Vector<3>,
Expand Down Expand Up @@ -154,26 +153,22 @@ mod tests {
let xz = Surface::xz_plane();

// Coincident and parallel planes don't have an intersection curve.
assert_eq!(SurfaceSurfaceIntersection::compute(&xy, &xy), None);
assert_eq!(SurfaceSurfaceIntersection::compute([&xy, &xy]), None);
assert_eq!(
SurfaceSurfaceIntersection::compute(
SurfaceSurfaceIntersection::compute([
&xy,
&xy.transform(&Transform::translation([0., 0., 1.]))
),
]),
None,
);

let expected_xy = Curve::build(xy).u_axis();
let expected_xz = Curve::build(xz).u_axis();

assert_eq!(
SurfaceSurfaceIntersection::compute(&xy, &xz),
SurfaceSurfaceIntersection::compute([&xy, &xz]),
Some(SurfaceSurfaceIntersection {
local_intersection_curves: [
*expected_xy.kind(),
*expected_xz.kind()
],
global_intersection_curve: *expected_xy.global().kind(),
intersection_curves: [expected_xy, expected_xz],
})
);
}
Expand Down