geomotif.core.spacing
¶
Spacing curves that control the distribution of points along a path.
A spacing curve is a monotonic mapping of normalized progress t in
[0, 1] to eased progress in [0, 1], with f(0) == 0 and f(1) == 1.
The eased value selects each point's position as a fraction of the path's
arc length, so the shape of the curve directly controls the gap between
consecutive points:
f(t) = t-> equal spacing- slow start / fast end -> spacing gradually increases
- fast start / slow end -> spacing gradually decreases
Because resampling is generic over polylines, these curves apply to every motif in the library -- spirals, fractals, tilings and string art alike.
Classes:
| Name | Description |
|---|---|
SpacingCurve |
Base class for point-spacing curves. |
LinearSpacing |
Equal spacing between every point (the default, a "0 curve"). |
PowerSpacing |
|
QuadraticSpacing |
Classic quadratic easing ( |
CubicSpacing |
Classic cubic easing ( |
SineSpacing |
Sinusoidal easing -- a gentle, natural-feeling bias. |
ExponentialSpacing |
Exponential easing with adjustable |
CircularSpacing |
Circular (quarter-arc) easing -- abrupt at one end, flat at the other. |
SmoothstepSpacing |
Hermite smoothstep |
ReversedSpacing |
Mirror any curve: dense where the original was sparse, and vice versa. |
CompositeSpacing |
Chain curves, feeding each one's output into the next. |
TableSpacing |
A curve drawn by hand, from arbitrary |
Functions:
| Name | Description |
|---|---|
coerce_spacing |
Normalize anything spacing-shaped into a :class: |
SpacingCurve
¶
Bases: ABC
Base class for point-spacing curves.
Subclasses must implement :meth:ease, mapping [0, 1] -> [0, 1]
monotonically with the endpoints fixed.
Methods:
| Name | Description |
|---|---|
ease |
Map a fraction of the way along the curve to a fraction of its length. |
LinearSpacing
¶
PowerSpacing
¶
Bases: _ModalCurve
t ** exponent -- the general-purpose "by how much" control.
exponent == 1-- equal spacing (identical to :class:LinearSpacing)exponent > 1-- with mode"in", spacing gradually increases; larger exponents exaggerate the effect0 < exponent < 1-- the opposite bias
Combine with mode="out" to flip which end is dense.
Source code in src/geomotif/core/spacing.py
QuadraticSpacing
¶
CubicSpacing
¶
SineSpacing
¶
ExponentialSpacing
¶
Bases: _ModalCurve
Exponential easing with adjustable strength (dramatic bias).
strength (default 10, the CSS/Penner standard) controls how extreme
the clustering is; higher values pack points ever more tightly at the
slow end. The curve is normalized so it still maps 0 -> 0 and 1 -> 1.
Source code in src/geomotif/core/spacing.py
CircularSpacing
¶
Bases: _ModalCurve
Circular (quarter-arc) easing -- abrupt at one end, flat at the other.
Source code in src/geomotif/core/spacing.py
SmoothstepSpacing
¶
Bases: SpacingCurve
Hermite smoothstep 3t^2 - 2t^3 -- inherently ease-in-out.
Spacing grows toward the middle of the path and shrinks again toward the end, with perfectly smooth acceleration.
ReversedSpacing
¶
Bases: SpacingCurve
Mirror any curve: dense where the original was sparse, and vice versa.
ReversedSpacing(f)(t) == 1 - f(1 - t), which is exactly the "out"
of a modal curve's "in" -- but this works on curves that have no mode,
including plain callables and :class:TableSpacing.
Source code in src/geomotif/core/spacing.py
CompositeSpacing
¶
Bases: SpacingCurve
Chain curves, feeding each one's output into the next.
CompositeSpacing(a, b)(t) == b(a(t)) -- written in application order,
so it reads left to right. Composition of monotone [0, 1] -> [0, 1] maps
is itself monotone with fixed endpoints, so the result is always a valid
spacing curve.
Source code in src/geomotif/core/spacing.py
TableSpacing
¶
Bases: SpacingCurve
A curve drawn by hand, from arbitrary (t, eased) control points.
Interpolation between control points is linear. That is a deliberate choice over a smoother spline: linear interpolation of monotone data is exactly monotone, whereas cubic fits can overshoot and hand back a curve that walks backwards -- which shows up as points in the wrong order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
sequence of (float, float)
|
Control points in [0, 1] x [0, 1]. |
required |
Examples:
A curve that spends the first half of its length on the first quarter of the path::
TableSpacing([(0.5, 0.25)])
Source code in src/geomotif/core/spacing.py
coerce_spacing
¶
coerce_spacing(spacing: SpacingLike | None) -> SpacingCurve
Normalize anything spacing-shaped into a :class:SpacingCurve.
None means :class:LinearSpacing. This is the single place the
library decides what counts as a spacing curve, so every entry point
accepts exactly the same things and fails the same way.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |