pub struct CurveCurveIntersection { /* private fields */ }Expand description
The intersection of two 3D curves.
Read it through hits, overlaps,
method, completeness,
is_complete and is_empty.
Intersect::intersect returns it,
reading the receiver’s parameters first; an exact result is always
complete, so an empty one proves the curves do not meet.
§Examples
use geomcore::{Circle, Intersect, IntersectionMethod, Line, Point, Tolerance, Vector};
// A line through a circle of radius 2 crosses it twice.
let line = Line::new(Point::new(-5.0, 0.0, 0.0), Vector::X).unwrap();
let circle = Circle::new(Point::ORIGIN, Vector::Z, 2.0).unwrap();
let result = line.intersect(&circle, Tolerance::DEFAULT);
assert_eq!(result.method(), IntersectionMethod::Exact);
assert!(result.is_complete());
// The line's parameters come out of the solve; the circle's angles do not.
let on_line: Vec<Option<f64>> = result.hits().iter().map(|h| h.first_parameter).collect();
assert_eq!(on_line, [Some(3.0), Some(7.0)]);
assert_eq!(result.hits()[0].second_parameter, None);Implementations§
Source§impl CurveCurveIntersection
impl CurveCurveIntersection
Sourcepub fn hits(&self) -> &[CurveCurveHit]
pub fn hits(&self) -> &[CurveCurveHit]
The isolated hits. A hit outside a trimmed curve’s range is dropped.
A parameter is stored only where the solver computed it: always on
the numeric path, on a line against a conic for the line, and on a
trimmed curve, whose range test needs it. A missing one is None;
recover it with the curve’s parameter_of(hit.point). The hits are
sorted by first parameter when every hit has one, and come in the
solver’s order otherwise.
§Examples
use geomcore::curves::TrimmedCurve;
use geomcore::{Circle, Intersect, Line, Point, Tolerance, Vector};
// An arc across the seam at angle 0 keeps only the hit at angle 0.
let line = Line::new(Point::new(-5.0, 0.0, 0.0), Vector::X).unwrap();
let circle = Circle::new(Point::ORIGIN, Vector::Z, 2.0).unwrap();
let arc = TrimmedCurve::new(circle, -1.0, 1.0).unwrap();
let result = arc.intersect(&line, Tolerance::DEFAULT);
let hit = result.hits()[0];
assert_eq!(result.hits().len(), 1);
// The arc's range test computed its angle; the line's comes from the solve.
assert_eq!(hit.first_parameter, Some(0.0));
assert_eq!(hit.second_parameter, Some(7.0));
assert!(hit.point.distance(Point::new(2.0, 0.0, 0.0)) < 1e-12);Sourcepub fn overlaps(&self) -> &[CurveCurveOverlap]
pub fn overlaps(&self) -> &[CurveCurveOverlap]
The ranges over which the curves coincide, sorted by the start of
the first range. Each range is increasing and lies in its curve’s
own range; an overlap crossing a closed curve’s seam comes in two
pieces. same_direction says whether the curves run the same way
along the overlap; with opposite directions, first_range.0 pairs
with second_range.1.
Two pieces of one curve that share at most tol.confusion of length
in space, or stand apart by at most that, such as consecutive
segments of a line, do not overlap: they meet at a hit, with
multiplicity 1.
On the numeric path an overlap is joined from the hits and regions
the search left where the curves never separated, and its ends lie
within tol.confusion in space of the true ones; the result stays
incomplete, with an Unseparated region over it. An overlap whose
range on the second curve would cross that curve’s seam is not
joined there: its hits and region stay.
§Examples
use geomcore::curves::TrimmedCurve;
use geomcore::{CurveCurveOverlap, Intersect, Line, Point, Tolerance, Vector};
// Two segments of one line share x in [1, 2].
let line = Line::new(Point::ORIGIN, Vector::X).unwrap();
let first = TrimmedCurve::new(line, 0.0, 2.0).unwrap();
let second = TrimmedCurve::new(line, 1.0, 3.0).unwrap();
let result = first.intersect(&second, Tolerance::DEFAULT);
assert!(result.hits().is_empty());
assert_eq!(
result.overlaps(),
&[CurveCurveOverlap {
first_range: (1.0, 2.0),
second_range: (1.0, 2.0),
same_direction: true,
}]
);Sourcepub fn method(&self) -> IntersectionMethod
pub fn method(&self) -> IntersectionMethod
Whether the result came from a closed form or a numeric search.
§Examples
use geomcore::{Circle, Intersect, IntersectionMethod, Point, Tolerance, Vector};
// A B-spline has no closed form: the numeric search runs.
let circle = Circle::new(Point::ORIGIN, Vector::Z, 2.0).unwrap();
let other = Circle::new(Point::new(2.0, 0.0, 0.0), Vector::Z, 2.0).unwrap();
let result = circle.intersect(&other.to_bspline(), Tolerance::DEFAULT);
assert_eq!(result.method(), IntersectionMethod::Numeric);
assert_eq!(result.hits().len(), 2);Sourcepub fn completeness(&self) -> &Completeness<CurveCurveRegion>
pub fn completeness(&self) -> &Completeness<CurveCurveRegion>
Whether every hit was found, and where hits may be missing if not.
§Examples
use geomcore::{Circle, Completeness, Intersect, Line, Point, Tolerance, Vector};
let line = Line::new(Point::ORIGIN, Vector::X).unwrap();
let circle = Circle::new(Point::ORIGIN, Vector::Z, 1.0).unwrap();
let result = circle.intersect(&line, Tolerance::DEFAULT);
assert_eq!(result.completeness(), &Completeness::Complete);Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Whether every hit was found.
§Examples
use geomcore::{Ellipse, Frame, Intersect, Line, Point, Tolerance, Vector};
let ellipse = Ellipse::from_frame(Frame::WORLD, 3.0, 1.0).unwrap();
let line = Line::new(Point::ORIGIN, Vector::Y).unwrap();
assert!(ellipse.intersect(&line, Tolerance::DEFAULT).is_complete());Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether no hit and no overlap was found. With an incomplete result this means “found nothing”, not “nothing exists”.
§Examples
use geomcore::{Intersect, Line, Point, Tolerance, Vector};
// An exact empty result proves the skew lines never meet.
let first = Line::new(Point::ORIGIN, Vector::X).unwrap();
let second = Line::new(Point::new(0.0, 0.0, 1.0), Vector::Y).unwrap();
let result = first.intersect(&second, Tolerance::DEFAULT);
assert!(result.is_empty() && result.is_complete());