Skip to content

pymath.interpolate_cubic

Daniel Flassig edited this page Jul 22, 2026 · 3 revisions

Interpolates a smooth cubic curve (B-Spline) through a list of points, returned as cubic Bézier segments.

pymath.interpolate_cubic(type, points [, start_tangent, end_tangent, knot_spans])
Parameter Type Description
type string "open" or "closed" (as in pytha.create_polyline).
points list of points Array of points to interpolate. Each point can be either an array of length d for d-dimensional space or a number in 1D.
start_tangent point (optional) For an "open" curve only, the tangent direction at the first point — the same shape as a point
end_tangent point (optional) For an "open" curve only, the tangent direction at the last point.
knot_spans list of numbers (optional) The parameter interval of each segment, replacing the default chord-length spacing: n positive numbers for "closed", n - 1 for "open".

Return value

Type Description
curve A flat list of control points describing the cubic Bézier segments, or nil if the curve could not be built (see Notes). Each control point has the same shape as an input point (a d-vector, or a plain number when points was given as a flat list of numbers). Successive segments share their joint control point: points 1..4 are the first segment, 4..7 the second, and so on. An "open" curve returns 3 * (n - 1) + 1 control points, a "closed" curve 3 * n (its last segment closes back to the first point).

Notes:

  • The curve passes through every input point: control point 3 * k + 1 equals input point k + 1.
  • Each group of four consecutive control points is a cubic Bézier segment that can be passed straight to pymath.eval_bezier.
  • For "closed", give the distinct vertices — do not repeat the first point at the end.
  • start_tangent / end_tangent are only relevant for an "open" curve; passing one with "closed" raises an error. Without them endpoints will receive a zero derivative. Without knot_spans only the direction is used — the tangent's length is ignored. With explicit knot_spans the tangent is the exact end derivative dp/dt and its magnitude is honored.
  • Without knot_spans, nil is returned when two consecutive points coincide. With knot_spans, coincident points are allowed (the spacing no longer comes from the point positions); nil is returned instead if any span is not positive.
  • Explicit knot spans are useful to construct an interpolating function from given function values f(x_i) (the spans are the differences of the consecutive x_i). In this case, the end tangents can be used to specify explicitly f'(x_1) and f'(x_n).

Example:

local pts = {{0, 0}, {1, 2}, {3, 1}, {4, 3}}
local cp = pymath.interpolate_cubic("open", pts)
-- #cp == 10                       -- 3 * (4 - 1) + 1 control points
-- cp[1] == {0, 0}, cp[4] == {1, 2}, cp[7] == {3, 1}, cp[10] == {4, 3}

-- sample the first Bézier segment at its midpoint
local mid = pymath.eval_bezier(0.5, cp[1], cp[2], cp[3], cp[4])

-- prescribe the end tangent directions (open curve): leave horizontally, arrive vertically
local cp2 = pymath.interpolate_cubic("open", pts, {1, 0}, {0, 1})

-- 1-D points as a flat list of numbers -> a flat list of numbers back
local y = pymath.interpolate_cubic("open", {0, 1, 3, 4})
-- #y == 10, y[1] == 0, y[4] == 1, y[7] == 3, y[10] == 4  (all plain numbers)

-- interpolate function values y = f(x) over non-uniform x, using the x-gaps as knot spans
local xs = {0, 1, 2, 4}          -- sample positions (may be non-uniform)
local ys = {0, 1, 1, 0}          -- function values (repeats are fine here)
local spans = {1, 1, 2}          -- xs[i+1] - xs[i]  (n - 1 spans for "open")
local fy = pymath.interpolate_cubic("open", ys, nil, nil, spans)

Version Support:

Minimum PYTHA Version: V27

See also:

pymath, pymath.eval_bezier, pymath.eval_bezier_deriv

Clone this wiki locally