-
-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #884 from hannobraun/intersection
Implement curve/edge intersection
- Loading branch information
Showing
3 changed files
with
217 additions
and
124 deletions.
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
crates/fj-kernel/src/algorithms/intersection/curve_edge.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
use fj_math::{Point, Segment}; | ||
use parry2d_f64::query::{Ray, RayCast}; | ||
|
||
use crate::objects::{Curve, Edge}; | ||
|
||
/// The intersection between a [`Curve`] and an [`Edge`], in curve coordinates | ||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] | ||
pub struct CurveEdgeIntersection { | ||
point_on_curve: Point<1>, | ||
} | ||
|
||
impl CurveEdgeIntersection { | ||
/// Construct an instance from a point on a curve | ||
pub fn from_point_on_curve(point_on_curve: impl Into<Point<1>>) -> Self { | ||
let point_on_curve = point_on_curve.into(); | ||
Self { point_on_curve } | ||
} | ||
|
||
/// Compute the intersection | ||
/// | ||
/// # Panics | ||
/// | ||
/// Currently, only intersections between lines and line segments can be | ||
/// computed. Panics, if a different type of [`Curve`] or [`Edge`] is | ||
/// passed. | ||
pub fn compute(curve: &Curve<2>, edge: &Edge) -> Option<Self> { | ||
let curve_as_line = match curve { | ||
Curve::Line(line) => line, | ||
_ => todo!("Curve-edge intersection only supports lines"), | ||
}; | ||
|
||
let edge_as_segment = { | ||
let line = match edge.curve().local_form() { | ||
Curve::Line(line) => line, | ||
_ => { | ||
todo!("Curve-edge intersection only supports line segments") | ||
} | ||
}; | ||
|
||
let vertices = match edge.vertices().get() { | ||
Some(vertices) => vertices.map(|vertex| { | ||
line.point_from_line_coords(vertex.position()) | ||
}), | ||
None => todo!( | ||
"Curve-edge intersection does not support continuous edges" | ||
), | ||
}; | ||
|
||
Segment::from_points(vertices) | ||
}; | ||
|
||
let ray = Ray { | ||
origin: curve_as_line.origin.to_na(), | ||
dir: curve_as_line.direction.to_na(), | ||
}; | ||
let ray_inv = Ray { | ||
origin: curve_as_line.origin.to_na(), | ||
dir: -curve_as_line.direction.to_na(), | ||
}; | ||
|
||
let result = edge_as_segment.to_parry().cast_local_ray( | ||
&ray, | ||
f64::INFINITY, | ||
false, | ||
); | ||
let result_inv = edge_as_segment.to_parry().cast_local_ray( | ||
&ray_inv, | ||
f64::INFINITY, | ||
false, | ||
); | ||
|
||
if let Some(result) = result { | ||
return Some(Self { | ||
point_on_curve: Point::from([result]), | ||
}); | ||
} | ||
if let Some(result_inv) = result_inv { | ||
return Some(Self { | ||
point_on_curve: Point::from([-result_inv]), | ||
}); | ||
} | ||
|
||
None | ||
} | ||
|
||
/// Access the intersection point on the curve | ||
pub fn point_on_curve(&self) -> Point<1> { | ||
self.point_on_curve | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use fj_math::Point; | ||
|
||
use crate::objects::{Curve, Edge, Surface}; | ||
|
||
use super::CurveEdgeIntersection; | ||
|
||
#[test] | ||
fn compute() { | ||
let surface = Surface::xy_plane(); | ||
|
||
let curve = Curve::u_axis(); | ||
|
||
let edge_left = Edge::build() | ||
.line_segment_from_points(&surface, [[-1., -1.], [-1., 1.]]); | ||
let edge_right = Edge::build() | ||
.line_segment_from_points(&surface, [[1., -1.], [1., 1.]]); | ||
let edge_below = Edge::build() | ||
.line_segment_from_points(&surface, [[-1., -1.], [1., -1.]]); | ||
|
||
let intersection_with_edge_left = | ||
CurveEdgeIntersection::compute(&curve, &edge_left); | ||
let intersection_with_edge_right = | ||
CurveEdgeIntersection::compute(&curve, &edge_right); | ||
let intersection_with_edge_below = | ||
CurveEdgeIntersection::compute(&curve, &edge_below); | ||
|
||
assert_eq!( | ||
intersection_with_edge_left, | ||
Some(CurveEdgeIntersection::from_point_on_curve(Point::from([ | ||
-1. | ||
]))) | ||
); | ||
assert_eq!( | ||
intersection_with_edge_right, | ||
Some(CurveEdgeIntersection::from_point_on_curve(Point::from([ | ||
1. | ||
]))) | ||
); | ||
assert!(intersection_with_edge_below.is_none()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.