svg_path/offset

Path offset construction.

This module follows the same basic model as svgpathsio: lines are offset exactly, while curves are converted to cubic Beziers and approximated by endpoint-normal cubics. The approximation is checked by sampling the true normal extrusion of the source curve and measuring its distance to the proposed offset. If the error is too large, the source curve is split and each half is offset recursively.

Subpath and path offsets create a provisional one-sided offset walk by connecting adjacent segment offsets with the requested join style. The public trimmed offset splits that walk at self-intersections, removes sections that lie inside the forbidden distance tube around the original subpath, then keeps the remaining sections in provisional traversal order. Because trimming can split an offset or remove it entirely, subpath and path offsets return Path.

The *_untrimmed helpers expose the provisional offset walk directly. It is useful for debugging, drawing raw construction geometry, or implementing a different trimming policy.

subpath_band and path_band construct two signed offset walks and trim them together. They do not add caps or bridges; this is the capless boundary primitive that stroke construction can build on later.

Types

Errors returned by offset helpers.

pub type Error {
  PathError(svg_path.Error)
  InvalidTolerance(tolerance: Float)
  InvalidSamples(samples: Int)
  InvalidMaxDepth(max_depth: Int)
  InvalidMiterLimit(miter_limit: Float)
  DegenerateTangent(t: Float)
  MaxDepthReached(error: Float)
  NonFinite
}

Constructors

  • PathError(svg_path.Error)

    An underlying path operation failed.

  • InvalidTolerance(tolerance: Float)

    The offset tolerance must be greater than zero.

  • InvalidSamples(samples: Int)

    The number of divergence samples must be greater than zero.

  • InvalidMaxDepth(max_depth: Int)

    The recursive subdivision limit must be greater than zero.

  • InvalidMiterLimit(miter_limit: Float)

    The miter limit must be greater than zero.

  • DegenerateTangent(t: Float)

    A segment tangent was too small to define a stable normal direction.

  • MaxDepthReached(error: Float)

    Refinement could not produce an offset within the requested tolerance.

  • NonFinite

    A calculation produced a non-finite coordinate.

Join style used when offsetting adjacent subpath segments.

pub type Join {
  Bevel
  Miter(miter_limit: Float)
  Round
}

Constructors

  • Bevel

    Connect adjacent offset segments with a straight line.

  • Miter(miter_limit: Float)

    Extend the offset tangents toward their intersection when the miter stays within miter_limit; otherwise fall back to Bevel.

  • Round

    Connect adjacent offset segments with a circular SVG arc.

Options for offset construction.

pub type Options {
  Options(
    tolerance: Float,
    max_depth: Int,
    samples: Int,
    distance: svg_path.DistanceOptions,
    join: Join,
  )
}

Constructors

Values

pub fn default_options() -> Options

Return default options for offset construction.

pub fn path(
  path: svg_path.Path,
  distance distance: Float,
) -> Result(svg_path.Path, Error)

Offset every subpath in a path by a signed distance.

pub fn path_band(
  path: svg_path.Path,
  distance_a distance_a: Float,
  distance_b distance_b: Float,
) -> Result(svg_path.Path, Error)

Offset every subpath in a path at two signed distances and trim each pair of sides together.

pub fn path_band_with(
  path path: svg_path.Path,
  distance_a distance_a: Float,
  distance_b distance_b: Float,
  options options: Options,
) -> Result(svg_path.Path, Error)

Offset every subpath in a path at two signed distances using explicit options.

pub fn path_untrimmed(
  path: svg_path.Path,
  distance distance: Float,
) -> Result(svg_path.Path, Error)

Offset every subpath in a path without trimming self-intersections.

pub fn path_untrimmed_with(
  path path: svg_path.Path,
  distance distance: Float,
  options options: Options,
) -> Result(svg_path.Path, Error)

Offset every subpath in a path without trimming self-intersections using explicit options.

pub fn path_with(
  path path: svg_path.Path,
  distance distance: Float,
  options options: Options,
) -> Result(svg_path.Path, Error)

Offset every subpath in a path by a signed distance using explicit options.

pub fn segment(
  segment: svg_path.Segment,
  distance distance: Float,
) -> Result(svg_path.Subpath, Error)

Offset one segment by a signed distance.

Positive distances offset to the right of the segment direction. For a line from (0, 0) to (10, 0), distance: 2.0 returns a line from (0, -2) to (10, -2).

Curves return an open subpath because the result may need several cubic pieces to stay within tolerance. Arcs and quadratic Beziers are converted to cubic Beziers before offsetting.

pub fn segment_with(
  segment segment: svg_path.Segment,
  distance distance: Float,
  options options: Options,
) -> Result(svg_path.Subpath, Error)

Offset one segment by a signed distance using explicit options.

pub fn subpath(
  subpath: svg_path.Subpath,
  distance distance: Float,
) -> Result(svg_path.Path, Error)

Offset a subpath by a signed distance.

Positive distances offset to the right of the subpath direction. Adjacent offset segments are connected using default_options().join. The result is a path because trimming self-intersections can split the offset into multiple subpaths or remove it entirely.

The provisional offset is split at self-intersections. Each section is sampled at global section-length parameters 0.1, 0.2, ..., 0.9; sections with fewer than five samples at least abs(distance) - options.tolerance from the original subpath are removed.

pub fn subpath_band(
  subpath: svg_path.Subpath,
  distance_a distance_a: Float,
  distance_b distance_b: Float,
) -> Result(svg_path.Path, Error)

Offset a subpath at two signed distances and trim the two sides together.

No caps, bridges, or fill-rule interpretation are added. The two provisional offset walks are split at their own self-intersections and at intersections with each other, then each section is tested against the original subpath’s distance tube. This supports ordinary capless stroke sides, one-sided bands, and asymmetric bands such as two positive offsets.

pub fn subpath_band_with(
  subpath subpath: svg_path.Subpath,
  distance_a distance_a: Float,
  distance_b distance_b: Float,
  options options: Options,
) -> Result(svg_path.Path, Error)

Offset a subpath at two signed distances using explicit options.

pub fn subpath_untrimmed(
  subpath: svg_path.Subpath,
  distance distance: Float,
) -> Result(svg_path.Subpath, Error)

Offset a subpath without trimming self-intersections.

This returns the provisional one-sided offset walk. Adjacent segment offsets are connected with default_options().join; the result may self-intersect or contain sections that a trimmed offset would remove.

pub fn subpath_untrimmed_with(
  subpath subpath: svg_path.Subpath,
  distance distance: Float,
  options options: Options,
) -> Result(svg_path.Subpath, Error)

Offset a subpath without trimming self-intersections using explicit options.

pub fn subpath_with(
  subpath subpath: svg_path.Subpath,
  distance distance: Float,
  options options: Options,
) -> Result(svg_path.Path, Error)

Offset a subpath by a signed distance using explicit options.

Search Document