Documentation
    Preparing search index...

    Function expandStroke

    • Expands polylines into the triangles of their stroke (§52 "stroke expansion", §58 StrokeStyle).

      const mesh = expandStroke(
      [{ points: [{ x: 0, y: 0 }, { x: 2, y: 0 }, { x: 2, y: 2 }], closed: false }],
      { width: 0.2, tolerance: 0.01, lineJoin: "round", lineCap: "square" },
      );
      mesh.indices.length / 3; // triangles: two quads, a round join, two caps

      One quad per segment, offset to StrokeGeometryOptions.alignment's side; one join at every interior vertex, and at every vertex of a closed ring; one cap at each end of an open polyline. Joins and caps are drawn on the corner's outer side only, which is the side a gap would otherwise appear on — the inner side of a corner is covered by the two quads already, twice.

      That double coverage is this function's one honest defect, and it is stated rather than worked around: under an opaque paint it is invisible, and under a translucent one the inside of every corner blends twice. The exact answer is a boolean union of the band with itself, which is the same planar-subdivision pass §52's self-intersection row waits on — see this module's header. alignment: "outside" on a convex outline avoids it entirely, because no corner's inner side is on the drawn side.

      A miter join extends both outer edges to their intersection, and falls back to bevel when the resulting spike is longer than StrokeGeometryOptions.miterLimit times the width — the SVG rule, and the reason the limit exists at all: at a hairpin the intersection runs off to infinity. A bevel join is the one triangle across the gap; a round join is a fan whose chords stay within StrokeGeometryOptions.tolerance of the true arc, the same sagitta bound Path.flatten uses on an arc command.

      A hairpin — two segments doubling exactly back on each other — has no bevel and no miter, only a round join; with the other two it leaves the notch its geometry actually has, rather than a wedge nobody asked for.

      A polyline of fewer than two distinct points strokes to nothing, and is dropped rather than refused: Path.flatten returns a lone moveTo as a single point and says explicitly that it is not the operation that gets to decide whether that is a dot, and this is that operation deciding — a dot is a Circle, and inventing one here would make every stray moveTo in an imported document sprout a blob. Consecutive duplicate points are dropped for the same reason: a zero-length segment has no direction to offset along. Non-finite coordinates are refused (§85).

      Parameters

      Returns StrokeMesh