pub struct Subpath<ManipulatorGroupId: Identifier> {
pub closed: bool,
/* private fields */
}
Expand description
Structure used to represent a path composed of Bezier curves.
Fields§
§closed: bool
Implementations§
source§impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
Functionality relating to core Subpath
operations, such as constructors and iter
.
sourcepub fn new(
manipulator_groups: Vec<ManipulatorGroup<ManipulatorGroupId>>,
closed: bool
) -> Self
pub fn new( manipulator_groups: Vec<ManipulatorGroup<ManipulatorGroupId>>, closed: bool ) -> Self
Create a new Subpath
using a list of ManipulatorGroups.
A Subpath
with less than 2 ManipulatorGroups may not be closed.
sourcepub fn from_bezier(bezier: &Bezier) -> Self
pub fn from_bezier(bezier: &Bezier) -> Self
Create a Subpath
consisting of 2 manipulator groups from a Bezier
.
sourcepub fn from_beziers(beziers: &[Bezier], closed: bool) -> Self
pub fn from_beziers(beziers: &[Bezier], closed: bool) -> Self
Creates a subpath from a slice of Bezier. When two consecutive Beziers do not share an end and start point, this function resolves the discrepancy by simply taking the start-point of the second Bezier as the anchor of the Manipulator Group.
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the Subpath
contains no ManipulatorGroup.
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of ManipulatorGroups contained within the Subpath
.
sourcepub fn len_segments(&self) -> usize
pub fn len_segments(&self) -> usize
Returns the number of segments contained within the Subpath
.
sourcepub fn get_segment(&self, segment_index: usize) -> Option<Bezier>
pub fn get_segment(&self, segment_index: usize) -> Option<Bezier>
Returns a copy of the bezier segment at the given segment index, if this segment exists.
sourcepub fn iter(&self) -> SubpathIter<'_, ManipulatorGroupId> ⓘ
pub fn iter(&self) -> SubpathIter<'_, ManipulatorGroupId> ⓘ
Returns an iterator of the Beziers along the Subpath
.
sourcepub fn manipulator_groups(&self) -> &[ManipulatorGroup<ManipulatorGroupId>]
pub fn manipulator_groups(&self) -> &[ManipulatorGroup<ManipulatorGroupId>]
Returns a slice of the ManipulatorGroups in the Subpath
.
sourcepub fn manipulator_groups_mut(
&mut self
) -> &mut Vec<ManipulatorGroup<ManipulatorGroupId>>
pub fn manipulator_groups_mut( &mut self ) -> &mut Vec<ManipulatorGroup<ManipulatorGroupId>>
Returns a mutable reference to the ManipulatorGroups in the Subpath
.
sourcepub fn anchors(&self) -> Vec<DVec2>
pub fn anchors(&self) -> Vec<DVec2>
Returns a vector of all the anchors (DVec2) for this Subpath
.
sourcepub fn curve_to_svg(&self, svg: &mut String, attributes: String)
pub fn curve_to_svg(&self, svg: &mut String, attributes: String)
Appends to the svg
mutable string with an SVG shape representation of the curve.
sourcepub fn subpath_to_svg(&self, svg: &mut String, transform: DAffine2) -> Result
pub fn subpath_to_svg(&self, svg: &mut String, transform: DAffine2) -> Result
Write the curve argument to the string (the d=“…” part)
sourcepub fn handle_lines_to_svg(&self, svg: &mut String, attributes: String)
pub fn handle_lines_to_svg(&self, svg: &mut String, attributes: String)
Appends to the svg
mutable string with an SVG shape representation of the handle lines.
sourcepub fn anchors_to_svg(&self, svg: &mut String, attributes: String)
pub fn anchors_to_svg(&self, svg: &mut String, attributes: String)
Appends to the svg
mutable string with an SVG shape representation of the anchors.
sourcepub fn handles_to_svg(&self, svg: &mut String, attributes: String)
pub fn handles_to_svg(&self, svg: &mut String, attributes: String)
Appends to the svg
mutable string with an SVG shape representation of the handles.
sourcepub fn to_svg(
&self,
svg: &mut String,
curve_attributes: String,
anchor_attributes: String,
handle_attributes: String,
handle_line_attributes: String
)
pub fn to_svg( &self, svg: &mut String, curve_attributes: String, anchor_attributes: String, handle_attributes: String, handle_line_attributes: String )
Returns an SVG representation of the Subpath
.
Appends to the svg
mutable string with an SVG shape representation that includes the curve, the handle lines, the anchors, and the handles.
sourcepub fn from_anchors(
anchor_positions: impl IntoIterator<Item = DVec2>,
closed: bool
) -> Self
pub fn from_anchors( anchor_positions: impl IntoIterator<Item = DVec2>, closed: bool ) -> Self
Construct a Subpath from an iter of anchor positions.
sourcepub fn new_rect(corner1: DVec2, corner2: DVec2) -> Self
pub fn new_rect(corner1: DVec2, corner2: DVec2) -> Self
Constructs a rectangle with corner1
and corner2
as the two corners.
sourcepub fn new_ellipse(corner1: DVec2, corner2: DVec2) -> Self
pub fn new_ellipse(corner1: DVec2, corner2: DVec2) -> Self
Constructs an ellipse with corner1
and corner2
as the two corners of the bounding box.
sourcepub fn new_regular_polygon(center: DVec2, sides: u64, radius: f64) -> Self
pub fn new_regular_polygon(center: DVec2, sides: u64, radius: f64) -> Self
Constructs a regular polygon (ngon). Based on sides
and radius
, which is the distance from the center to any vertex.
sourcepub fn new_star_polygon(
center: DVec2,
sides: u64,
radius: f64,
inner_radius: f64
) -> Self
pub fn new_star_polygon( center: DVec2, sides: u64, radius: f64, inner_radius: f64 ) -> Self
Constructs a star polygon (n-star). See [new_regular_polygon], but with interspersed vertices at an inner_radius
.
sourcepub fn new_cubic_spline(points: Vec<DVec2>) -> Self
pub fn new_cubic_spline(points: Vec<DVec2>) -> Self
Construct a cubic spline from a list of points. Based on https://mathworld.wolfram.com/CubicSpline.html.
source§impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
Functionality relating to looking up properties of the Subpath
or points along the Subpath
.
sourcepub fn compute_lookup_table(
&self,
steps: Option<usize>,
tvalue_type: Option<TValueType>
) -> Vec<DVec2>
pub fn compute_lookup_table( &self, steps: Option<usize>, tvalue_type: Option<TValueType> ) -> Vec<DVec2>
Return a selection of equidistant points on the bezier curve.
If no value is provided for steps
, then the function will default steps
to be 10.
sourcepub fn length(&self, num_subdivisions: Option<usize>) -> f64
pub fn length(&self, num_subdivisions: Option<usize>) -> f64
Return the sum of the approximation of the length of each Bezier
curve along the Subpath
.
num_subdivisions
- Number of subdivisions used to approximate the curve. The default value is1000
.
sourcepub fn global_euclidean_to_local_euclidean(
&self,
global_t: f64,
lengths: &[f64],
total_length: f64
) -> (usize, f64)
pub fn global_euclidean_to_local_euclidean( &self, global_t: f64, lengths: &[f64], total_length: f64 ) -> (usize, f64)
Converts from a subpath (composed of multiple segments) to a point along a certain segment represented.
The returned tuple represents the segment index and the t
value along that segment.
Both the input global t
value and the output t
value are in euclidean space, meaning there is a constant rate of change along the arc length.
sourcepub fn project(
&self,
point: DVec2,
options: Option<ProjectionOptions>
) -> Option<(usize, f64)>
pub fn project( &self, point: DVec2, options: Option<ProjectionOptions> ) -> Option<(usize, f64)>
Returns the segment index and t
value that corresponds to the closest point on the curve to the provided point.
Uses a searching algorithm akin to binary search that can be customized using the ProjectionOptions structure.
source§impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
sourcepub fn set_closed(&mut self, new_closed: bool)
pub fn set_closed(&mut self, new_closed: bool)
Set whether the subpath is closed.
sourcepub fn manipulator_from_id(
&self,
id: ManipulatorGroupId
) -> Option<&ManipulatorGroup<ManipulatorGroupId>>
pub fn manipulator_from_id( &self, id: ManipulatorGroupId ) -> Option<&ManipulatorGroup<ManipulatorGroupId>>
Access a ManipulatorGroup from a ManipulatorGroupId.
sourcepub fn manipulator_mut_from_id(
&mut self,
id: ManipulatorGroupId
) -> Option<&mut ManipulatorGroup<ManipulatorGroupId>>
pub fn manipulator_mut_from_id( &mut self, id: ManipulatorGroupId ) -> Option<&mut ManipulatorGroup<ManipulatorGroupId>>
Access a mutable ManipulatorGroup from a ManipulatorGroupId.
sourcepub fn manipulator_index_from_id(&self, id: ManipulatorGroupId) -> Option<usize>
pub fn manipulator_index_from_id(&self, id: ManipulatorGroupId) -> Option<usize>
Access the index of a ManipulatorGroup from a ManipulatorGroupId.
sourcepub fn insert_manipulator_group(
&mut self,
index: usize,
group: ManipulatorGroup<ManipulatorGroupId>
)
pub fn insert_manipulator_group( &mut self, index: usize, group: ManipulatorGroup<ManipulatorGroupId> )
Insert a manipulator group at an index.
sourcepub fn push_manipulator_group(
&mut self,
group: ManipulatorGroup<ManipulatorGroupId>
)
pub fn push_manipulator_group( &mut self, group: ManipulatorGroup<ManipulatorGroupId> )
Push a manipulator group to the end.
sourcepub fn last_manipulator_group_mut(
&mut self
) -> Option<&mut ManipulatorGroup<ManipulatorGroupId>>
pub fn last_manipulator_group_mut( &mut self ) -> Option<&mut ManipulatorGroup<ManipulatorGroupId>>
Get a mutable reference to the last manipulator
sourcepub fn remove_manipulator_group(
&mut self,
index: usize
) -> ManipulatorGroup<ManipulatorGroupId>
pub fn remove_manipulator_group( &mut self, index: usize ) -> ManipulatorGroup<ManipulatorGroupId>
Remove a manipulator group at an index.
sourcepub fn insert(&mut self, t: SubpathTValue)
pub fn insert(&mut self, t: SubpathTValue)
Inserts a ManipulatorGroup
at a certain point along the subpath based on the parametric t
-value provided.
Expects t
to be within the inclusive range [0, 1]
.
sourcepub fn append_bezier(&mut self, bezier: &Bezier, append_type: AppendType)
pub fn append_bezier(&mut self, bezier: &Bezier, append_type: AppendType)
Append a Bezier to the end of a subpath from a vector of Bezier.
The append_type
parameter determines how the function behaves when the subpath’s last anchor is not equal to the Bezier’s start point.
IgnoreStart
: drops the bezier’s start point in favor of the subpath’s last anchorSmoothJoin(f64)
: joins the subpath’s endpoint with the bezier’s start with a another Bezier segment that is continuous up to the second derivative if the difference between the subpath’s end point and Bezier’s start point exceeds the wrapped integer value. This function assumes that the position of the Bezier’s starting point is equal to that of the Subpath’s last manipulator group.
source§impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
sourcepub fn evaluate(&self, t: SubpathTValue) -> DVec2
pub fn evaluate(&self, t: SubpathTValue) -> DVec2
Calculate the point on the subpath based on the parametric t
-value provided.
Expects t
to be within the inclusive range [0, 1]
.
sourcepub fn intersections(
&self,
other: &Bezier,
error: Option<f64>,
minimum_separation: Option<f64>
) -> Vec<(usize, f64)>
pub fn intersections( &self, other: &Bezier, error: Option<f64>, minimum_separation: Option<f64> ) -> Vec<(usize, f64)>
Calculates the intersection points the subpath has with a given curve and returns a list of (usize, f64)
tuples,
where the usize
represents the index of the curve in the subpath, and the f64
represents the t
-value local to
that curve where the intersection occurred.
Expects the following:
other
: a Bezier curve to check intersections againsterror
: an optional f64 value to provide an error boundminimum_separation
: the minimum difference two adjacentt
-values must have when comparing adjacentt
-values in sorted order. If the comparison condition is not satisfied, the function takes the largert
-value of the two.
sourcepub fn subpath_intersections(
&self,
other: &Subpath<ManipulatorGroupId>,
error: Option<f64>,
minimum_separation: Option<f64>
) -> Vec<(usize, f64)>
pub fn subpath_intersections( &self, other: &Subpath<ManipulatorGroupId>, error: Option<f64>, minimum_separation: Option<f64> ) -> Vec<(usize, f64)>
Calculates the intersection points the subpath has with another given subpath and returns a list of global parametric t
-values.
This function expects the following:
- other: a Bezier curve to check intersections against
- error: an optional f64 value to provide an error bound
sourcepub fn ray_test_crossings_count(
&self,
ray_start: DVec2,
ray_direction: DVec2
) -> usize
pub fn ray_test_crossings_count( &self, ray_start: DVec2, ray_direction: DVec2 ) -> usize
Returns how many times a given ray intersects with this subpath. (ray_direction
does not need to be normalized.)
If this needs to be called frequently with a ray of the same rotation angle, consider instead using [ray_test_crossings_count_prerotated
].
sourcepub fn ray_test_crossings_count_prerotated(
&self,
ray_start: DVec2,
rotation_matrix: DMat2,
rotated_subpath: &Self
) -> usize
pub fn ray_test_crossings_count_prerotated( &self, ray_start: DVec2, rotation_matrix: DMat2, rotated_subpath: &Self ) -> usize
Returns how many times a given ray intersects with this subpath. (ray_direction
does not need to be normalized.)
This version of the function is for better performance when calling it frequently without needing to change the rotation between each call.
If that isn’t important, use [ray_test_crossings_count
] which provides an easier interface by taking a ray direction vector.
Instead, this version requires a rotation matrix for the ray’s rotation and a prerotated version of this subpath that has had its rotation applied.
sourcepub fn point_inside(&self, point: DVec2) -> bool
pub fn point_inside(&self, point: DVec2) -> bool
Returns true if the given point is inside this subpath. Open paths are NOT automatically closed so you’ll need to call set_closed(true)
before calling this.
Self-intersecting subpaths use the evenodd
fill rule for checking in/outside-ness: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule.
If this needs to be called frequently, consider instead using [point_inside_prerotated
] and moving this function’s setup code into your own logic before the repeated call.
sourcepub fn point_inside_prerotated(
&self,
point: DVec2,
rotation_matrix1: DMat2,
rotation_matrix2: DMat2,
rotated_subpath1: &Self,
rotated_subpath2: &Self
) -> bool
pub fn point_inside_prerotated( &self, point: DVec2, rotation_matrix1: DMat2, rotation_matrix2: DMat2, rotated_subpath1: &Self, rotated_subpath2: &Self ) -> bool
Returns true if the given point is inside this subpath. Open paths are NOT automatically closed so you’ll need to call set_closed(true)
before calling this.
Self-intersecting subpaths use the evenodd
fill rule for checking in/outside-ness: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-rule.
This version of the function is for better performance when calling it frequently because it lets the caller precompute the rotations once instead of every call.
If that isn’t important, use [point_inside
] which provides an easier interface.
Instead, this version requires a pair of rotation matrices for the ray’s rotation and a pair of prerotated versions of this subpath.
They should face in different directions that are unlikely to align in the real world. Consider using the following rotations:
const SIN_13DEG: f64 = 0.22495105434;
const COS_13DEG: f64 = 0.97437006478;
const DIRECTION1: DVec2 = DVec2::new(SIN_13DEG, COS_13DEG);
const DIRECTION2: DVec2 = DVec2::new(-COS_13DEG, -SIN_13DEG);
sourcepub fn self_intersections(
&self,
error: Option<f64>,
minimum_separation: Option<f64>
) -> Vec<(usize, f64)>
pub fn self_intersections( &self, error: Option<f64>, minimum_separation: Option<f64> ) -> Vec<(usize, f64)>
Returns a list of t
values that correspond to the self intersection points of the subpath. For each intersection point, the returned t
value is the smaller of the two that correspond to the point.
error
- For intersections with non-linear beziers,error
defines the threshold for bounding boxes to be considered an intersection point.minimum_separation
: the minimum difference two adjacentt
-values must have when comparing adjacentt
-values in sorted order. If the comparison condition is not satisfied, the function takes the largert
-value of the two
NOTE: if an intersection were to occur within an error
distance away from an anchor point, the algorithm will filter that intersection out.
sourcepub fn rectangle_intersections(
&self,
corner1: DVec2,
corner2: DVec2,
error: Option<f64>,
minimum_separation: Option<f64>
) -> Vec<(usize, f64)>
pub fn rectangle_intersections( &self, corner1: DVec2, corner2: DVec2, error: Option<f64>, minimum_separation: Option<f64> ) -> Vec<(usize, f64)>
Calculates the intersection points the subpath has with a given rectangle and returns a list of (usize, f64)
tuples,
where the usize
represents the index of the curve in the subpath, and the f64
represents the t
-value local to
that curve where the intersection occurred.
Expects the following:
corner1
: any corner of the axis-aligned box to intersect withcorner2
: the corner opposite tocorner1
error
: an optional f64 value to provide an error boundminimum_separation
: the minimum difference two adjacentt
-values must have when comparing adjacentt
-values in sorted order. If the comparison condition is not satisfied, the function takes the largert
-value of the two.
sourcepub fn rectangle_intersections_exist(
&self,
corner1: DVec2,
corner2: DVec2
) -> bool
pub fn rectangle_intersections_exist( &self, corner1: DVec2, corner2: DVec2 ) -> bool
Checks if any intersections exist between this subpath and the four edges of the rectangle defined by the top-left corner1
and bottom-right corner2
.
This is faster than calling [rectangle_intersections
].len()
because it short-circuits as soon as an intersection is found.
sourcepub fn tangent(&self, t: SubpathTValue) -> DVec2
pub fn tangent(&self, t: SubpathTValue) -> DVec2
Returns a normalized unit vector representing the tangent on the subpath based on the parametric t
-value provided.
sourcepub fn normal(&self, t: SubpathTValue) -> DVec2
pub fn normal(&self, t: SubpathTValue) -> DVec2
Returns a normalized unit vector representing the direction of the normal on the subpath based on the parametric t
-value provided.
sourcepub fn local_extrema(&self) -> [Vec<f64>; 2]
pub fn local_extrema(&self) -> [Vec<f64>; 2]
Returns two lists of t
-values representing the local extrema of the x
and y
parametric subpaths respectively.
The list of t
-values returned are filtered such that they fall within the range [0, 1]
.
sourcepub fn bounding_box(&self) -> Option<[DVec2; 2]>
pub fn bounding_box(&self) -> Option<[DVec2; 2]>
Return the min and max corners that represent the bounding box of the subpath.
sourcepub fn bounding_box_with_transform(
&self,
transform: DAffine2
) -> Option<[DVec2; 2]>
pub fn bounding_box_with_transform( &self, transform: DAffine2 ) -> Option<[DVec2; 2]>
Return the min and max corners that represent the bounding box of the subpath, after a given affine transform.
sourcepub fn inflections(&self) -> Vec<f64>
pub fn inflections(&self) -> Vec<f64>
Returns list of t
-values representing the inflection points of the subpath.
The list of t
-values returned are filtered such that they fall within the range [0, 1]
.
sourcepub fn contains_point(&self, target_point: DVec2) -> bool
pub fn contains_point(&self, target_point: DVec2) -> bool
Does a path contain a point? Based on the non zero winding
sourcepub fn poisson_disk_points(
&self,
separation_disk_diameter: f64,
rng: impl FnMut() -> f64
) -> Vec<DVec2>
pub fn poisson_disk_points( &self, separation_disk_diameter: f64, rng: impl FnMut() -> f64 ) -> Vec<DVec2>
Randomly places points across the filled surface of this subpath (which is assumed to be closed).
The separation_disk_diameter
determines the minimum distance between all points from one another.
Conceptually, this works by “throwing a dart” at the subpath’s bounding box and keeping the dart only if:
- It’s inside the shape
- It’s not closer than
separation_disk_diameter
to any other point from a previous accepted dart throw This repeats until accepted darts fill all possible areas between one another.
While the conceptual process described above asymptotically slows down and is never guaranteed to produce a maximal set in finite time, this is implemented with an algorithm that produces a maximal set in O(n) time. The slowest part is actually checking if points are inside the subpath shape.
sourcepub fn curvature(&self, t: SubpathTValue) -> f64
pub fn curvature(&self, t: SubpathTValue) -> f64
Returns the curvature, a scalar value for the derivative at the point t
along the subpath.
Curvature is 1 over the radius of a circle with an equivalent derivative.
source§impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
impl<ManipulatorGroupId: Identifier> Subpath<ManipulatorGroupId>
Functionality that transforms Subpaths, such as split, reduce, offset, etc.
sourcepub fn split(
&self,
t: SubpathTValue
) -> (Subpath<ManipulatorGroupId>, Option<Subpath<ManipulatorGroupId>>)
pub fn split( &self, t: SubpathTValue ) -> (Subpath<ManipulatorGroupId>, Option<Subpath<ManipulatorGroupId>>)
Returns either one or two Subpaths that result from splitting the original Subpath at the point corresponding to t
.
If the original Subpath was closed, a single open Subpath will be returned.
If the original Subpath was open, two open Subpaths will be returned.
sourcepub fn reverse(&self) -> Subpath<ManipulatorGroupId>
pub fn reverse(&self) -> Subpath<ManipulatorGroupId>
Returns a Subpath with a reversed winding order. Note that a reversed closed subpath will start on the same manipulator group and simply wind the other direction
sourcepub fn trim(
&self,
t1: SubpathTValue,
t2: SubpathTValue
) -> Subpath<ManipulatorGroupId>
pub fn trim( &self, t1: SubpathTValue, t2: SubpathTValue ) -> Subpath<ManipulatorGroupId>
Returns an open Subpath that results from trimming the original Subpath between the points corresponding to t1
and t2
, maintaining the winding order of the original.
If the original Subpath is closed, the order of arguments does matter.
The resulting Subpath will wind from the given t1
to t2
.
That means, if the value of t1
> t2
, it will cross the break between endpoints from t1
to t = 1 = 0
to t2
.
If a path winding in the reverse direction is desired, call trim
on the Subpath
returned from Subpath::reverse
.
sourcepub fn apply_transform(&mut self, affine_transform: DAffine2)
pub fn apply_transform(&mut self, affine_transform: DAffine2)
Apply a transformation to all of the ManipulatorGroups in the Subpath.
sourcepub fn rotate(&self, angle: f64) -> Subpath<ManipulatorGroupId>
pub fn rotate(&self, angle: f64) -> Subpath<ManipulatorGroupId>
Returns a subpath that results from rotating this subpath around the origin by the given angle (in radians).
sourcepub fn rotate_about_point(
&self,
angle: f64,
pivot: DVec2
) -> Subpath<ManipulatorGroupId>
pub fn rotate_about_point( &self, angle: f64, pivot: DVec2 ) -> Subpath<ManipulatorGroupId>
Returns a subpath that results from rotating this subpath around the provided point by the given angle (in radians).
sourcepub fn offset(&self, distance: f64, join: Join) -> Subpath<ManipulatorGroupId>
pub fn offset(&self, distance: f64, join: Join) -> Subpath<ManipulatorGroupId>
Reduces the segments of the subpath into simple subcurves, then scales each subcurve a set distance
away.
The intersections of segments of the subpath are joined using the method specified by the join
argument.
sourcepub fn outline(
&self,
distance: f64,
join: Join,
cap: Cap
) -> (Subpath<ManipulatorGroupId>, Option<Subpath<ManipulatorGroupId>>)
pub fn outline( &self, distance: f64, join: Join, cap: Cap ) -> (Subpath<ManipulatorGroupId>, Option<Subpath<ManipulatorGroupId>>)
Outline returns a single closed subpath (if the original subpath was open) or two closed subpaths (if the original subpath was closed) that forms an approximate outline around the subpath at a specified distance from the curve. Outline takes the following parameters:
distance
- The outline’s distance from the curve.join
- The join type used to cap the endpoints of open bezier curves, and join successive subpath segments.