Trait cavalier_contours::polyline::PlineSource
source · pub trait PlineSource {
type Num: Real;
type OutputPolyline: PlineCreation<Num = Self::Num>;
Show 37 methods
// Required methods
fn vertex_count(&self) -> usize;
fn is_closed(&self) -> bool;
fn get(&self, index: usize) -> Option<PlineVertex<Self::Num>>;
fn at(&self, index: usize) -> PlineVertex<Self::Num>;
// Provided methods
fn iter_segments(&self) -> SegmentIter<'_, Self> ⓘ { ... }
fn iter_vertexes(&self) -> VertexIter<'_, Self> ⓘ { ... }
fn is_empty(&self) -> bool { ... }
fn fuzzy_eq_eps<P>(&self, other: &P, eps: Self::Num) -> bool
where P: PlineSource<Num = Self::Num> + ?Sized { ... }
fn fuzzy_eq<P>(&self, other: &P) -> bool
where P: PlineSource<Num = Self::Num> + ?Sized { ... }
fn last(&self) -> Option<PlineVertex<Self::Num>> { ... }
fn segment_count(&self) -> usize { ... }
fn iter_segment_indexes(&self) -> PlineSegIndexIterator ⓘ { ... }
fn next_wrapping_index(&self, i: usize) -> usize { ... }
fn prev_wrapping_index(&self, i: usize) -> usize { ... }
fn fwd_wrapping_dist(&self, start_index: usize, end_index: usize) -> usize { ... }
fn fwd_wrapping_index(&self, start_index: usize, offset: usize) -> usize { ... }
fn extents(&self) -> Option<AABB<Self::Num>> { ... }
fn path_length(&self) -> Self::Num { ... }
fn area(&self) -> Self::Num { ... }
fn orientation(&self) -> PlineOrientation { ... }
fn remove_repeat_pos(
&self,
pos_equal_eps: Self::Num
) -> Option<Self::OutputPolyline> { ... }
fn remove_redundant(
&self,
pos_equal_eps: Self::Num
) -> Option<Self::OutputPolyline> { ... }
fn rotate_start(
&self,
start_index: usize,
point: Vector2<Self::Num>,
pos_equal_eps: Self::Num
) -> Option<Self::OutputPolyline> { ... }
fn create_approx_aabb_index(&self) -> Option<StaticAABB2DIndex<Self::Num>> { ... }
fn create_aabb_index(&self) -> Option<StaticAABB2DIndex<Self::Num>> { ... }
fn closest_point(
&self,
point: Vector2<Self::Num>,
pos_equal_eps: Self::Num
) -> Option<ClosestPointResult<Self::Num>> { ... }
fn winding_number(&self, point: Vector2<Self::Num>) -> i32 { ... }
fn arcs_to_approx_lines(
&self,
error_distance: Self::Num
) -> Option<Self::OutputPolyline> { ... }
fn visit_self_intersects<C, V>(&self, visitor: &mut V) -> C
where C: ControlFlow,
V: PlineIntersectVisitor<Self::Num, C> { ... }
fn visit_self_intersects_opt<C, V>(
&self,
visitor: &mut V,
options: &PlineSelfIntersectOptions<'_, Self::Num>
) -> C
where C: ControlFlow,
V: PlineIntersectVisitor<Self::Num, C> { ... }
fn find_intersects<P>(
&self,
other: &P
) -> PlineIntersectsCollection<Self::Num>
where P: PlineSource<Num = Self::Num> + ?Sized { ... }
fn find_intersects_opt<P>(
&self,
other: &P,
options: &FindIntersectsOptions<'_, Self::Num>
) -> PlineIntersectsCollection<Self::Num>
where P: PlineSource<Num = Self::Num> + ?Sized { ... }
fn parallel_offset(&self, offset: Self::Num) -> Vec<Self::OutputPolyline> { ... }
fn parallel_offset_opt(
&self,
offset: Self::Num,
options: &PlineOffsetOptions<'_, Self::Num>
) -> Vec<Self::OutputPolyline> { ... }
fn boolean<P>(
&self,
other: &P,
operation: BooleanOp
) -> BooleanResult<Self::OutputPolyline>
where P: PlineSource<Num = Self::Num> + ?Sized { ... }
fn boolean_opt<P>(
&self,
other: &P,
operation: BooleanOp,
options: &PlineBooleanOptions<'_, Self::Num>
) -> BooleanResult<Self::OutputPolyline>
where P: PlineSource<Num = Self::Num> + ?Sized { ... }
fn find_point_at_path_length(
&self,
target_path_length: Self::Num
) -> Result<(usize, Vector2<Self::Num>), Self::Num> { ... }
}
Expand description
Trait representing a readonly source of polyline data. This trait has all the methods and operations that can be performed on a readonly polyline.
A polyline is a sequence of vertexes and a bool indicating whether the polyline is closed (last vertex forms segment with first vertex) or open (no segment between last and first vertex). For related traits see PlineSourceMut and PlineCreation.
Each vertex has a 2d xy position and bulge value. See PlineVertex for more information.
Required Associated Types§
sourcetype OutputPolyline: PlineCreation<Num = Self::Num>
type OutputPolyline: PlineCreation<Num = Self::Num>
Type used for output when invoking methods that return a new polyline.
Required Methods§
sourcefn vertex_count(&self) -> usize
fn vertex_count(&self) -> usize
Total number of vertexes.
sourcefn get(&self, index: usize) -> Option<PlineVertex<Self::Num>>
fn get(&self, index: usize) -> Option<PlineVertex<Self::Num>>
Get the vertex at given index
position. Returns None
if index
out of bounds.
sourcefn at(&self, index: usize) -> PlineVertex<Self::Num>
fn at(&self, index: usize) -> PlineVertex<Self::Num>
Same as PlineSource::get but panics if index
is out of bounds.
Panics
Panics if index
is out of bounds.
Provided Methods§
sourcefn iter_segments(&self) -> SegmentIter<'_, Self> ⓘ
fn iter_segments(&self) -> SegmentIter<'_, Self> ⓘ
Return iterator to iterate over all the polyline segments.
sourcefn iter_vertexes(&self) -> VertexIter<'_, Self> ⓘ
fn iter_vertexes(&self) -> VertexIter<'_, Self> ⓘ
Return iterator to iterate over all the polyline vertexes.
sourcefn fuzzy_eq_eps<P>(&self, other: &P, eps: Self::Num) -> boolwhere
P: PlineSource<Num = Self::Num> + ?Sized,
fn fuzzy_eq_eps<P>(&self, other: &P, eps: Self::Num) -> boolwhere P: PlineSource<Num = Self::Num> + ?Sized,
Fuzzy compare with another polyline using eps
epsilon value for fuzzy comparison of
vertexes.
sourcefn fuzzy_eq<P>(&self, other: &P) -> boolwhere
P: PlineSource<Num = Self::Num> + ?Sized,
fn fuzzy_eq<P>(&self, other: &P) -> boolwhere P: PlineSource<Num = Self::Num> + ?Sized,
Same as PlineSource::fuzzy_eq_eps but uses default Self::Num::fuzzy_epsilon()
.
sourcefn last(&self) -> Option<PlineVertex<Self::Num>>
fn last(&self) -> Option<PlineVertex<Self::Num>>
Get the last vertex of the polyline or None
if polyline is empty.
sourcefn segment_count(&self) -> usize
fn segment_count(&self) -> usize
Total number of segments in the polyline.
sourcefn iter_segment_indexes(&self) -> PlineSegIndexIterator ⓘ
fn iter_segment_indexes(&self) -> PlineSegIndexIterator ⓘ
Iterate through all the polyline segment vertex positional indexes.
Segments are represented by polyline vertex pairs, for each vertex there is an associated positional index in the polyline, this method iterates through those positional indexes as segment pairs starting at (0, 1) and ending at (n-2, n-1) if open polyline or (n-1, 0) if closed polyline where n is the number of vertexes.
sourcefn next_wrapping_index(&self, i: usize) -> usize
fn next_wrapping_index(&self, i: usize) -> usize
Returns the next wrapping vertex index for the polyline.
If i + 1 >= self.len()
then 0 is returned, otherwise i + 1
is returned.
sourcefn prev_wrapping_index(&self, i: usize) -> usize
fn prev_wrapping_index(&self, i: usize) -> usize
Returns the previous wrapping vertex index for the polyline.
If i == 0
then self.len() - 1
is returned, otherwise i - 1
is returned.
sourcefn fwd_wrapping_dist(&self, start_index: usize, end_index: usize) -> usize
fn fwd_wrapping_dist(&self, start_index: usize, end_index: usize) -> usize
Returns the forward wrapping distance between two vertex indexes.
Assumes start_index
is valid, debug asserts start_index < self.len()
.
Examples
let mut polyline = Polyline::new_closed();
polyline.add(0.0, 0.0, 0.0);
polyline.add(0.0, 0.0, 0.0);
polyline.add(0.0, 0.0, 0.0);
polyline.add(0.0, 0.0, 0.0);
assert_eq!(polyline.fwd_wrapping_dist(0, 2), 2);
assert_eq!(polyline.fwd_wrapping_dist(3, 1), 2);
sourcefn fwd_wrapping_index(&self, start_index: usize, offset: usize) -> usize
fn fwd_wrapping_index(&self, start_index: usize, offset: usize) -> usize
Returns the vertex index after applying offset
to start_index
in a wrapping manner.
Assumes start_index
is valid, debug asserts start_index < self.len()
.
Assumes offset
does not wrap multiple times, debug asserts offset <= self.len()
.
Examples
let mut polyline = Polyline::new_closed();
polyline.add(0.0, 0.0, 0.0);
polyline.add(0.0, 0.0, 0.0);
polyline.add(0.0, 0.0, 0.0);
polyline.add(0.0, 0.0, 0.0);
assert_eq!(polyline.fwd_wrapping_index(0, 2), 2);
assert_eq!(polyline.fwd_wrapping_index(1, 2), 3);
assert_eq!(polyline.fwd_wrapping_index(1, 3), 0);
assert_eq!(polyline.fwd_wrapping_index(2, 3), 1);
sourcefn extents(&self) -> Option<AABB<Self::Num>>
fn extents(&self) -> Option<AABB<Self::Num>>
Compute the XY extents of the polyline.
Returns None
if polyline has less than 2 vertexes.
Examples
let mut polyline = Polyline::new();
assert_eq!(polyline.extents(), None);
polyline.add(1.0, 1.0, 1.0);
assert_eq!(polyline.extents(), None);
polyline.add(3.0, 1.0, 1.0);
let extents = polyline.extents().unwrap();
assert!(extents.min_x.fuzzy_eq(1.0));
assert!(extents.min_y.fuzzy_eq(0.0));
assert!(extents.max_x.fuzzy_eq(3.0));
assert!(extents.max_y.fuzzy_eq(1.0));
polyline.set_is_closed(true);
let extents = polyline.extents().unwrap();
assert!(extents.min_x.fuzzy_eq(1.0));
assert!(extents.min_y.fuzzy_eq(0.0));
assert!(extents.max_x.fuzzy_eq(3.0));
assert!(extents.max_y.fuzzy_eq(2.0));
sourcefn path_length(&self) -> Self::Num
fn path_length(&self) -> Self::Num
Returns the total path length of the polyline.
Examples
let mut polyline: Polyline = Polyline::new();
// open polyline half circle
polyline.add(0.0, 0.0, 1.0);
polyline.add(2.0, 0.0, 1.0);
assert!(polyline.path_length().fuzzy_eq(std::f64::consts::PI));
// close into full circle
polyline.set_is_closed(true);
assert!(polyline.path_length().fuzzy_eq(2.0 * std::f64::consts::PI));
sourcefn area(&self) -> Self::Num
fn area(&self) -> Self::Num
Compute the closed signed area of the polyline.
If PlineSource::is_closed is false (open polyline) then 0.0 is always returned. The area is signed such that if the polyline direction is counter clockwise then the area is positive, otherwise it is negative.
Examples
let mut polyline: Polyline = Polyline::new();
assert!(polyline.area().fuzzy_eq(0.0));
polyline.add(1.0, 1.0, 1.0);
assert!(polyline.area().fuzzy_eq(0.0));
polyline.add(3.0, 1.0, 1.0);
// polyline is still open so area is 0
assert!(polyline.area().fuzzy_eq(0.0));
polyline.set_is_closed(true);
assert!(polyline.area().fuzzy_eq(std::f64::consts::PI));
polyline.invert_direction_mut();
assert!(polyline.area().fuzzy_eq(-std::f64::consts::PI));
sourcefn orientation(&self) -> PlineOrientation
fn orientation(&self) -> PlineOrientation
Returns the orientation of the polyline.
This method just uses the PlineSource::area function to determine directionality of a closed polyline which may not yield a useful result if the polyline has self intersects.
sourcefn remove_repeat_pos(
&self,
pos_equal_eps: Self::Num
) -> Option<Self::OutputPolyline>
fn remove_repeat_pos( &self, pos_equal_eps: Self::Num ) -> Option<Self::OutputPolyline>
Remove all repeat position vertexes from the polyline.
Returns None
to avoid allocation and copy in the case that no vertexes are removed.
Examples
let mut polyline = Polyline::new_closed();
polyline.add(2.0, 2.0, 0.5);
polyline.add(2.0, 2.0, 1.0);
polyline.add(3.0, 3.0, 1.0);
polyline.add(3.0, 3.0, 0.5);
let result = polyline.remove_repeat_pos(1e-5).expect("repeat position vertexes were removed");
assert_eq!(result.vertex_count(), 2);
assert!(result[0].fuzzy_eq(PlineVertex::new(2.0, 2.0, 1.0)));
assert!(result[1].fuzzy_eq(PlineVertex::new(3.0, 3.0, 0.5)));
sourcefn remove_redundant(
&self,
pos_equal_eps: Self::Num
) -> Option<Self::OutputPolyline>
fn remove_redundant( &self, pos_equal_eps: Self::Num ) -> Option<Self::OutputPolyline>
Remove all redundant vertexes from the polyline.
Redundant vertexes can arise with multiple vertexes on top of each other, along a straight line, or forming a concentric arc with sweep angle less than or equal to PI.
Returns None
to avoid allocation and copy in the case that no vertexes are removed.
Examples
Removing repeat vertexes along a line
let mut polyline = Polyline::new_closed();
polyline.add(2.0, 2.0, 0.0);
polyline.add(3.0, 3.0, 0.0);
polyline.add(3.0, 3.0, 0.0);
polyline.add(4.0, 4.0, 0.0);
polyline.add(2.0, 4.0, 0.0);
let result = polyline.remove_redundant(1e-5).expect("redundant vertexes were removed");
assert_eq!(result.vertex_count(), 3);
assert!(result.is_closed());
assert!(result[0].fuzzy_eq(PlineVertex::new(2.0, 2.0, 0.0)));
assert!(result[1].fuzzy_eq(PlineVertex::new(4.0, 4.0, 0.0)));
assert!(result[2].fuzzy_eq(PlineVertex::new(2.0, 4.0, 0.0)));
Simplifying a circle defined by 5 vertexes
let bulge = (std::f64::consts::PI / 8.0).tan();
let mut polyline = Polyline::new_closed();
polyline.add(-0.5, 0.0, bulge);
polyline.add(0.0, -0.5, bulge);
// repeat vertex thrown in
polyline.add(0.0, -0.5, bulge);
polyline.add(0.5, 0.0, bulge);
polyline.add(0.0, 0.5, bulge);
let result = polyline.remove_redundant(1e-5).expect("redundant vertexes were removed");
assert_eq!(result.vertex_count(), 2);
assert!(result.is_closed());
assert!(result[0].fuzzy_eq(PlineVertex::new(-0.5, 0.0, 1.0)));
assert!(result[1].fuzzy_eq(PlineVertex::new(0.5, 0.0, 1.0)));
sourcefn rotate_start(
&self,
start_index: usize,
point: Vector2<Self::Num>,
pos_equal_eps: Self::Num
) -> Option<Self::OutputPolyline>
fn rotate_start( &self, start_index: usize, point: Vector2<Self::Num>, pos_equal_eps: Self::Num ) -> Option<Self::OutputPolyline>
Rotates the vertexes in a closed polyline such that the first vertex’s position is at
point
. start_index
indicates which segment point
lies on before rotation. This does
not change the shape of the polyline curve. pos_equal_eps
is epsilon value used for
comparing the positions of points. None
is returned if the polyline is not closed, the
polyline length is less than 2, or the start_index
is out of bounds.
Examples
let mut polyline = Polyline::new_closed();
assert!(matches!(polyline.rotate_start(0, Vector2::new(0.0, 0.0), 1e-5), None));
polyline.add(0.0, 0.0, 0.0);
assert!(matches!(polyline.rotate_start(0, Vector2::new(0.0, 0.0), 1e-5), None));
polyline.add(1.0, 0.0, 0.0);
polyline.add(1.0, 1.0, 0.0);
polyline.add(0.0, 1.0, 0.0);
let rot = polyline.rotate_start(0, Vector2::new(0.5, 0.0), 1e-5).unwrap();
let mut expected_rot = Polyline::new_closed();
expected_rot.add(0.5, 0.0, 0.0);
expected_rot.add(1.0, 0.0, 0.0);
expected_rot.add(1.0, 1.0, 0.0);
expected_rot.add(0.0, 1.0, 0.0);
expected_rot.add(0.0, 0.0, 0.0);
assert!(rot.fuzzy_eq(&expected_rot));
sourcefn create_approx_aabb_index(&self) -> Option<StaticAABB2DIndex<Self::Num>>
fn create_approx_aabb_index(&self) -> Option<StaticAABB2DIndex<Self::Num>>
Creates a fast approximate spatial index of all the polyline segments.
The starting vertex index position is used as the key to the segment bounding box in the
StaticAABB2DIndex
. The bounding boxes are guaranteed to be no smaller than the actual
bounding box of the segment but may be larger, this is done for performance. If you want the
actual bounding box index use PlineSource::create_aabb_index instead.
Returns None
if polyline vertex count is less than 2 or an error occurs in constructing
the spatial index.
sourcefn create_aabb_index(&self) -> Option<StaticAABB2DIndex<Self::Num>>
fn create_aabb_index(&self) -> Option<StaticAABB2DIndex<Self::Num>>
Creates a spatial index of all the polyline segments.
The starting vertex index position is used as the key to the segment bounding box in the
StaticAABB2DIndex
. The bounding boxes are the actual bounding box of the segment, for
performance reasons you may want to use PlineSource::create_approx_aabb_index.
Returns None
if polyline vertex count is less than 2 or an error occurs in constructing
the spatial index.
sourcefn closest_point(
&self,
point: Vector2<Self::Num>,
pos_equal_eps: Self::Num
) -> Option<ClosestPointResult<Self::Num>>
fn closest_point( &self, point: Vector2<Self::Num>, pos_equal_eps: Self::Num ) -> Option<ClosestPointResult<Self::Num>>
Find the closest segment point on a polyline to a point
given.
If the polyline is empty then None
is returned.
pos_equal_eps
is epsilon value used for fuzzy float comparisons.
Examples
let mut polyline: Polyline = Polyline::new();
assert!(matches!(polyline.closest_point(Vector2::zero(), 1e-5), None));
polyline.add(1.0, 1.0, 1.0);
let result = polyline.closest_point(Vector2::new(1.0, 0.0), 1e-5).unwrap();
assert_eq!(result.seg_start_index, 0);
assert!(result.seg_point.fuzzy_eq(polyline[0].pos()));
assert!(result.distance.fuzzy_eq(1.0));
sourcefn winding_number(&self, point: Vector2<Self::Num>) -> i32
fn winding_number(&self, point: Vector2<Self::Num>) -> i32
Calculate the winding number for a point
relative to the polyline.
The winding number calculates the number of turns/windings around a point that the polyline path makes. For a closed polyline without self intersects there are only three possibilities:
- -1 (polyline winds around point clockwise)
- 0 (point is outside the polyline)
- 1 (polyline winds around the point counter clockwise).
For a self intersecting closed polyline the winding number may be less than -1 (if the polyline winds around the point more than once in the counter clockwise direction) or greater than 1 (if the polyline winds around the point more than once in the clockwise direction).
This function always returns 0 if polyline PlineSource::is_closed is false.
If the point lies directly on top of one of the polyline segments the result is not defined (it may return any integer). To handle the case of the point lying directly on the polyline PlineSource::closest_point may be used to check if the distance from the point to the polyline is zero.
Examples
Polyline without self intersects
let mut polyline: Polyline = Polyline::new_closed();
polyline.add(0.0, 0.0, 1.0);
polyline.add(2.0, 0.0, 1.0);
assert_eq!(polyline.winding_number(Vector2::new(1.0, 0.0)), 1);
assert_eq!(polyline.winding_number(Vector2::new(0.0, 2.0)), 0);
polyline.invert_direction_mut();
assert_eq!(polyline.winding_number(Vector2::new(1.0, 0.0)), -1);
Multiple windings with self intersecting polyline
let mut polyline: Polyline = Polyline::new_closed();
polyline.add(0.0, 0.0, 1.0);
polyline.add(2.0, 0.0, 1.0);
polyline.add(0.0, 0.0, 1.0);
polyline.add(4.0, 0.0, 1.0);
assert_eq!(polyline.winding_number(Vector2::new(1.0, 0.0)), 2);
assert_eq!(polyline.winding_number(Vector2::new(-1.0, 0.0)), 0);
polyline.invert_direction_mut();
assert_eq!(polyline.winding_number(Vector2::new(1.0, 0.0)), -2);
sourcefn arcs_to_approx_lines(
&self,
error_distance: Self::Num
) -> Option<Self::OutputPolyline>
fn arcs_to_approx_lines( &self, error_distance: Self::Num ) -> Option<Self::OutputPolyline>
Returns a new polyline with all arc segments converted to line segments with some
error_distance
or None if T fails to cast to or from usize.
error_distance
is the maximum distance from any line segment to the arc it is
approximating. Line segments are circumscribed by the arc (all line end points lie on the
arc path).
sourcefn visit_self_intersects<C, V>(&self, visitor: &mut V) -> Cwhere
C: ControlFlow,
V: PlineIntersectVisitor<Self::Num, C>,
fn visit_self_intersects<C, V>(&self, visitor: &mut V) -> Cwhere C: ControlFlow, V: PlineIntersectVisitor<Self::Num, C>,
Visit self intersects of the polyline using default options.
sourcefn visit_self_intersects_opt<C, V>(
&self,
visitor: &mut V,
options: &PlineSelfIntersectOptions<'_, Self::Num>
) -> Cwhere
C: ControlFlow,
V: PlineIntersectVisitor<Self::Num, C>,
fn visit_self_intersects_opt<C, V>( &self, visitor: &mut V, options: &PlineSelfIntersectOptions<'_, Self::Num> ) -> Cwhere C: ControlFlow, V: PlineIntersectVisitor<Self::Num, C>,
Visit self intersects of the polyline using options provided.
sourcefn find_intersects<P>(&self, other: &P) -> PlineIntersectsCollection<Self::Num>where
P: PlineSource<Num = Self::Num> + ?Sized,
fn find_intersects<P>(&self, other: &P) -> PlineIntersectsCollection<Self::Num>where P: PlineSource<Num = Self::Num> + ?Sized,
Find all intersects between two polylines using default options.
sourcefn find_intersects_opt<P>(
&self,
other: &P,
options: &FindIntersectsOptions<'_, Self::Num>
) -> PlineIntersectsCollection<Self::Num>where
P: PlineSource<Num = Self::Num> + ?Sized,
fn find_intersects_opt<P>( &self, other: &P, options: &FindIntersectsOptions<'_, Self::Num> ) -> PlineIntersectsCollection<Self::Num>where P: PlineSource<Num = Self::Num> + ?Sized,
Find all intersects between two polylines using the options provided.
sourcefn parallel_offset(&self, offset: Self::Num) -> Vec<Self::OutputPolyline>
fn parallel_offset(&self, offset: Self::Num) -> Vec<Self::OutputPolyline>
Compute the parallel offset polylines of the polyline using default options.
offset
determines what offset polylines are generated, if it is positive then the
direction of the offset is to the left of the polyline segment tangent vectors otherwise it
is to the right.
Algorithm will use PlineOffsetOptions::default for algorithm options.
Examples
let pline = pline_closed![(0.0, 0.0, 1.0), (1.0, 0.0, 1.0)];
let offset_plines = pline.parallel_offset(0.2);
assert_eq!(offset_plines.len(), 1);
let offset_pline = &offset_plines[0];
assert!(offset_pline[0].fuzzy_eq(PlineVertex::new(0.2, 0.0, 1.0)));
assert!(offset_pline[1].fuzzy_eq(PlineVertex::new(0.8, 0.0, 1.0)));
sourcefn parallel_offset_opt(
&self,
offset: Self::Num,
options: &PlineOffsetOptions<'_, Self::Num>
) -> Vec<Self::OutputPolyline>
fn parallel_offset_opt( &self, offset: Self::Num, options: &PlineOffsetOptions<'_, Self::Num> ) -> Vec<Self::OutputPolyline>
Compute the parallel offset polylines of the polyline with options given.
offset
determines what offset polylines are generated, if it is positive then the
direction of the offset is to the left of the polyline segment tangent vectors otherwise it
is to the right.
options
is a struct that holds optional parameters. See
PlineOffsetOptions for specific parameters.
Examples
let pline = pline_closed![(0.0, 0.0, 1.0), (1.0, 0.0, 1.0)];
let aabb_index = pline.create_approx_aabb_index().unwrap();
let options = PlineOffsetOptions {
// setting option to handle possible self intersects in the polyline
handle_self_intersects: true,
// passing in existing spatial index of the polyline segments
aabb_index: Some(&aabb_index),
..Default::default()
};
let offset_plines = pline.parallel_offset_opt(0.2, &options);
assert_eq!(offset_plines.len(), 1);
let offset_pline = &offset_plines[0];
assert!(offset_pline[0].fuzzy_eq(PlineVertex::new(0.2, 0.0, 1.0)));
assert!(offset_pline[1].fuzzy_eq(PlineVertex::new(0.8, 0.0, 1.0)));
sourcefn boolean<P>(
&self,
other: &P,
operation: BooleanOp
) -> BooleanResult<Self::OutputPolyline>where
P: PlineSource<Num = Self::Num> + ?Sized,
fn boolean<P>( &self, other: &P, operation: BooleanOp ) -> BooleanResult<Self::OutputPolyline>where P: PlineSource<Num = Self::Num> + ?Sized,
Perform a boolean operation
between this polyline and another using default options.
See PlineSource::boolean_opt for more information.
Examples
let rectangle = pline_closed![
(-1.0, -2.0, 0.0),
(3.0, -2.0, 0.0),
(3.0, 2.0, 0.0),
(-1.0, 2.0, 0.0),
];
let circle = pline_closed![(0.0, 0.0, 1.0), (2.0, 0.0, 1.0)];
let results = rectangle.boolean(&circle, BooleanOp::Not);
// since the circle is inside the rectangle we get back 1 positive polyline and 1 negative
// polyline where the positive polyline is the rectangle and the negative polyline is the
// circle
assert_eq!(results.pos_plines.len(), 1);
assert_eq!(results.neg_plines.len(), 1);
assert!(matches!(results.result_info, BooleanResultInfo::Pline2InsidePline1));
assert!(results.pos_plines[0].pline.area().fuzzy_eq(rectangle.area()));
assert!(results.neg_plines[0].pline.area().fuzzy_eq(circle.area()));
sourcefn boolean_opt<P>(
&self,
other: &P,
operation: BooleanOp,
options: &PlineBooleanOptions<'_, Self::Num>
) -> BooleanResult<Self::OutputPolyline>where
P: PlineSource<Num = Self::Num> + ?Sized,
fn boolean_opt<P>( &self, other: &P, operation: BooleanOp, options: &PlineBooleanOptions<'_, Self::Num> ) -> BooleanResult<Self::OutputPolyline>where P: PlineSource<Num = Self::Num> + ?Sized,
Perform a boolean operation
between this polyline and another with options provided.
Returns the boolean result polylines and their associated slices that were stitched together
end to end to form them. For the result pline1
refers to self
, and pline2
refers to
other
.
Examples
let rectangle = pline_closed![
(-1.0, -2.0, 0.0),
(3.0, -2.0, 0.0),
(3.0, 2.0, 0.0),
(-1.0, 2.0, 0.0),
];
let circle = pline_closed![(0.0, 0.0, 1.0), (2.0, 0.0, 1.0)];
let aabb_index = rectangle.create_approx_aabb_index().unwrap();
let options = PlineBooleanOptions {
// passing in existing spatial index of the polyline segments for the first polyline
pline1_aabb_index: Some(&aabb_index),
..Default::default()
};
let results = rectangle.boolean_opt(&circle, BooleanOp::Not, &options);
// since the circle is inside the rectangle we get back 1 positive polyline and 1 negative
// polyline where the positive polyline is the rectangle and the negative polyline is the
// circle
assert_eq!(results.pos_plines.len(), 1);
assert_eq!(results.neg_plines.len(), 1);
assert!(matches!(results.result_info, BooleanResultInfo::Pline2InsidePline1));
assert!(results.pos_plines[0].pline.area().fuzzy_eq(rectangle.area()));
assert!(results.neg_plines[0].pline.area().fuzzy_eq(circle.area()));
sourcefn find_point_at_path_length(
&self,
target_path_length: Self::Num
) -> Result<(usize, Vector2<Self::Num>), Self::Num>
fn find_point_at_path_length( &self, target_path_length: Self::Num ) -> Result<(usize, Vector2<Self::Num>), Self::Num>
Find the segment index and point on the polyline corresponding to the path length given.
Returns Ok((0, first_vertex_position))
if target_path_length
is negative.
Returns Ok((seg_index, point))
if target_path_length
is less than or equal to the
polyline’s total path length. Where seg_index
is the index of the segment the point lies
on, e.g. if point is on the second segment of the polyline then seg_index = 1
.
Returns Err((total_path_length))
if target_path_length
is greater than total path
length of the polyline.