from typing import Sequence from .charts_shape_line_path import point_runs, svg_pair 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