Functional Weave
Code in Rust

charts.shape@1.0.1

impl/python/step_path.py

1,275 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from typing import Sequence

from .charts_shape_line_path import point_runs, svg_pair  ← linePath, another function of this group · built into the same file, even by a slim install
from .charts_shape_types import Point, StepPosition


def step_path(points: Sequence[Point], position: StepPosition) -> str:
    """A step line as SVG path data, as d3.curveStepBefore, d3.curveStep and
    d3.curveStepAfter draw it: horizontal then vertical moves only."""
    if position == "before":
        t = 0.0
    elif position == "middle":
        t = 0.5
    elif position == "after":
        t = 1.0
    else:
        raise ValueError("step position must be before, middle or after, received %r" % (position,))
    out = ""
    for run in point_runs(points):
        out += "M" + svg_pair(run[0][0], run[0][1])
        for i in range(1, len(run)):
            px, py = run[i - 1]
            x, y = run[i]
            if t <= 0:
                out += "L" + svg_pair(px, y) + "L" + svg_pair(x, y)
            else:
                # d3's own expression, so the midpoint rounds as d3's does.
                x1 = px * (1 - t) + x * t
                out += "L" + svg_pair(x1, py) + "L" + svg_pair(x1, y)
        if 0 < t < 1 and len(run) >= 2:
            lx, ly = run[-1]
            out += "L" + svg_pair(lx, ly)
        if len(run) == 1:
            out += "Z"
    return out