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
def _sign(x: float) -> float:
return -1.0 if x < 0 else 1.0
def _slope3(x0: float, y0: float, x1: float, y1: float, x2: float, y2: float) -> float:
# Fritsch–Carlson: the tangent at the middle point, limited so the curve
# cannot overshoot either neighbouring value. d3's slope3.
h0 = x1 - x0
h1 = x2 - x1
s0 = (y1 - y0) / h0
s1 = (y2 - y1) / h1
p = (s0 * h1 + s1 * h0) / (h0 + h1)
t = (_sign(s0) + _sign(s1)) * min(abs(s0), abs(s1), 0.5 * abs(p))
return t if t != 0 else 0.0
def _slope2(x0: float, y0: float, x1: float, y1: float, t: float) -> float:
return (3 * (y1 - y0) / (x1 - x0) - t) / 2
def _bezier(x0: float, y0: float, x1: float, y1: float, t0: float, t1: float) -> str:
dx = (x1 - x0) / 3
return "C" + svg_pair(x0 + dx, y0 + dx * t0) + "," + svg_pair(x1 - dx, y1 - dx * t1) + "," + svg_pair(x1, y1)
def monotone_curve(points: Sequence[Point]) -> str:
"""A smooth line that stays monotone wherever the data is: d3.curveMonotoneX,
Hermite segments with Fritsch–Carlson tangents, as cubic Béziers."""
out = ""
for run in point_runs(points):
for i in range(1, len(run)):
if not run[i][0] > run[i - 1][0]:
raise ValueError(
"monotone curve needs x strictly increasing, but %r follows %r" % (run[i][0], run[i - 1][0])
)
out += "M" + svg_pair(run[0][0], run[0][1])
n = len(run)
if n == 1:
out += "Z"
continue
if n == 2:
out += "L" + svg_pair(run[1][0], run[1][1])
continue
t0 = 0.0
for i in range(2, n):
ax, ay = run[i - 2]
bx, by = run[i - 1]
cx, cy = run[i]
t1 = _slope3(ax, ay, bx, by, cx, cy)
start = _slope2(ax, ay, bx, by, t1) if i == 2 else t0
out += _bezier(ax, ay, bx, by, start, t1)
t0 = t1
ax, ay = run[n - 2]
bx, by = run[n - 1]
out += _bezier(ax, ay, bx, by, t0, _slope2(ax, ay, bx, by, t0))
return out