# Handling Bezier Paths (Splines)

class beziers.path.BezierPath

  Bases: `BooleanOperationsMixin`, `SampleMixin`, `object`

  BezierPath represents a collection of Segment objects - the curves and lines that make up a path.

  One of the really fiddly things about manipulating Bezier paths in a computer is that there are various ways to represent them. Different applications prefer different representations. For instance, when you’re drawing a path on a canvas, you often want a list of nodes like so:

      { "x":255.0, "y":20.0, "type":"curve"},
      { "x":385.0, "y":20.0, "type":"offcurve"},
      { "x":526.0, "y":79.0, "type":"offcurve"},
      { "x":566.0, "y":135.0, "type":"curve"},
      { "x":585.0, "y":162.0, "type":"offcurve"},
      { "x":566.0, "y":260.0, "type":"offcurve"},
      { "x":484.0, "y":281.0, "type":"curve"},
      ...

  But when you’re doing Clever Bezier Mathematics, you generally want a list of segments instead:

      [ (255.0,20.0), (385.0,20.0), (526.0,79.0), (566.0,135.0)],
      [ (566.0,135.0), (585.0,162.0), (566.0,260.0), (484.0,281.0)],

  The Beziers module is designed to allow you to move fluidly between these different representations depending on what you’re wanting to do.

  classmethod fromPoints(points, error=50.0, cornerTolerance=20.0, maxSegments=20)
    Fit a poly-bezier curve to the points given. This operation should be familiar

      from ‘pencil’ tools in a vector drawing application: the application samples points where your mouse pointer has been dragged, and then turns the sketch into a Bezier path. The goodness of fit can be controlled by tuning the error parameter. Corner detection can be controlled with cornerTolerance.

      Here are some points fit with error=100.0:

    And with error=10.0:

  classmethod fromSegments(array: List[Segment])

    Construct a path from an array of Segment objects.

  classmethod fromNodelist(array: List[Node], closed=True)

    Construct a path from an array of Node objects.

  classmethod fromGlyphsLayer(layer: GSLayer)

    Returns an array of BezierPaths from a Glyphs GSLayer object.

  classmethod fromDrawable(layer, *penArgs, **penKwargs)

    Returns an array of BezierPaths from any object conforming to the pen protocol.

  classmethod fromFonttoolsGlyph(font, glyphname)

    Returns an array of BezierPaths from a FontTools font object and glyph name.

  asSegments() → List[Segment]

    Return the path as a list of segments (either Line, CubicBezier, or, if you are exceptionally unlucky, QuadraticBezier objects).

  asNodelist() → List[Node]

    Return the path as a list of Node objects.

  asSVGPath() → str

    Return the path as a string suitable for a SVG <path d=”…”? element.

  asMatplot()
  plot(ax, **kwargs)

    Plot the path on a Matplot subplot which you supply

        import matplotlib.pyplot as plt
        fig, ax = plt.subplots()
        path.plot(ax)

  clone() → BezierPath

    Return a new path which is an exact copy of this one

  round() → None

    Rounds the points of this path to integer coordinates.

  bounds() → BoundingBox

    Determine the bounding box of the path, returned as a BoundingBox object.

  splitAtPoints(splitlist: List[Tuple[Segment, float]])

    Split the path at the given points. The splitlist is a list of tuples, each containing a segment and a time (0->1) along that segment. For instance, to split a path at the midpoint of the first segment, you would do:

        path.splitAtPoints([(path.asSegments()[0], 0.5)])

  addExtremes() → BezierPath

    Add extreme points to the path.

  property length: float

    Returns the length of the whole path.

  pointAtTime(t: float) → Point

    Returns the point at time t (0->1) along the curve, where 1 is the end of the whole curve.

  lengthAtTime(t: float) → float

    Returns the length of the subset of the path from the start up to the point t (0->1), where 1 is the end of the whole curve.

  offset(vector: Point, rotateVector=True) → BezierPath
    Returns a new BezierPath which approximates offsetting the

      current Bezier path by the given vector. Note that the vector will be rotated around the normal of the curve so that the offsetting always happens on the same ‘side’ of the curve:

    If you don’t want that and you want ‘straight’ offsetting instead (which may intersect with the original curve), pass rotateVector=False:

  append(other: BezierPath, joinType='line') → BezierPath

    Append another path to this one. If the end point of the first path is not the same as the start point of the other path, a line will be drawn between them.

  reverse() → BezierPath

    Reverse this path (mutates path).

  translate(vector: Point) → BezierPath

    Translates the path by a given vector.

  rotate(about: Point, angle: float) → BezierPath

    Rotate the path by a given vector.

  scale(by: float) → BezierPath

    Scales the path by a given magnitude.

  balance() → None

    Performs Tunni balancing on the path.

  findDiscontinuities()

    Not implemented yet

  roundCorners()

    Not implemented yet

  dash(lineLength=50, gapLength=None) → List[BezierPath]
    Returns a list of BezierPath objects created by chopping

      this path into a dashed line:

          paths = path.dash(lineLength = 20, gapLength = 50)

  segpairs() → Iterator[Tuple[Segment, Segment]]

    Returns an iterator of pairs of segments.

  harmonize(seg1, seg2)
  flatten(degree=8) → BezierPath

    Returns a Path made up of line segments that approximate the path.

  windingNumberOfPoint(pt: Point) → int

    Returns the winding number of a point with respect to the path.

  pointIsInside(pt: Point) → bool

    Returns true if the given point lies on the “inside” of the path, assuming an ‘even-odd’ winding rule where self-intersections are considered outside.

  property signed_area: float

    Approximates the area under a closed path by flattening and treating as a polygon. Returns the signed area; positive means the path is counter-clockwise, negative means it is clockwise.

  property area: float

    Approximates the area under a closed path by flattening and treating as a polygon. Returns the unsigned area. Use `signed_area()` if you want the signed area.

  property direction: int

    Returns the direction of the path: -1 for clockwise and 1 for counterclockwise.

  property centroid: Point | None

    Returns the centroid of the path’s bounding box, or None if the path is open.

  drawWithBrush(other: BezierPath) → List[BezierPath]

    Assuming that other is a closed Bezier path representing a pen or brush of a certain shape and that self is an open path, this method traces the brush along the path, returning an array of Bezier paths.

    other may also be a function which, given a time t (0-1), returns a closed path representing the shape of the brush at the given time.

    This requires the shapely library to be installed.

  quadraticsToCubics() → None

    Converts all quadratic segments in the path to cubic Beziers.

  thicknessAtX(x: float) → float | None

    Returns the thickness of the path at x-coordinate `x`.

  distanceToPath(other: BezierPath, samples=10) → float

    Finds the distance to the other curve at its closest point, along with the t values for the closest point at each segment and the relevant segments.

    Returns: `distance, t1, t2, seg1, seg2`.

  tidy(**kwargs) → None

    Tidies a curve by adding extremes, and then running `removeIrrelevantSegments` and `smooth`. `relLength`, `absLength`, `maxCollectionSize`, `lengthLimit` and `cornerTolerance` parameters are passed to the relevant routine.

  removeIrrelevantSegments(relLength=2e-05, absLength=0)

    Removes small and collinear line segments. Collinear line segments are adjacent line segments which are heading in the same direction, and hence can be collapsed into a single segment. Small segments (those less than `absLength` units, or less than `relLength` as a fraction of the path’s total length) are removed entirely.

  smooth(maxCollectionSize=30, lengthLimit=20, cornerTolerance=10)

    Smooths a curve, by collating lists of small (at most `lengthLimit` units long) segments at most `maxCollectionSize` segments at a time, and running them through a curve fitting algorithm. The list collation also stops when one segment turns more than `cornerTolerance` degrees away from the previous one, so that corners are not smoothed.

## Subpackages

- beziers.path.representations package
  - Submodules
  - beziers.path.representations.GSPath module
    - `GSPathRepresentation`
      - `GSPathRepresentation.toNodelist()`
  - beziers.path.representations.Nodelist module
    - `Node`
      - `Node.x`
      - `Node.y`
    - `NodelistRepresentation`
      - `NodelistRepresentation.data()`
      - `NodelistRepresentation.toNodelist()`
      - `NodelistRepresentation.fromNodelist()`
  - beziers.path.representations.Segment module
    - `SegmentRepresentation`
      - `SegmentRepresentation.data()`
      - `SegmentRepresentation.toNodelist()`
      - `SegmentRepresentation.appendSegment()`
      - `SegmentRepresentation.fromNodelist()`
  - Module contents