
CatSmoothing: Smoothing Shapely Geometries with Catmull-Rom Splines¶
Overview¶
CatSmoothing smooths Shapely geometries,
LineString and (Multi)Polygon, using the Catmull-Rom spline algorithm and can
compute tangent angles at each vertex of a list of lines. The implementation is based on
the Splines library, but
offers performance improvements and additional features.
You can try CatSmoothing directly in your browser by clicking the Binder badge above.
Key Features¶
- Written in Rust for performance and runs in parallel using Rayon
- Creating splines from 2D vertices of a line that allows computing n-th derivatives
- Smoothing geometries with Centripetal Catmull-Rom splines with uniform spacing (points are spaced by equal arc length, computed with Gauss-Legendre quadrature)
- Computing tangent vectors at each vertex of a line
- Optional vertex pre-smoothing to reduce noise before fitting: a Gaussian filter with sigma in vertices or in length along the line, or Taubin smoothing that keeps the size of well-sampled shapes
- Optional curvature continuity (G2 or C2) through continuity-enhancing splits
Installation¶
Install CatSmoothing via pip or micromamba:
Using pip:
Using micromamba (or conda/mamba):
Quick Start¶
CatSmoothing provide one class called CatmullRom that is general purpose, Catmull-Rom
spline interpolation class. You can tweak the alpha parameter of the class to
interpolate with different versions of the Catmull-Rom spline from 2D vertices of a line
and compute n-th derivatives. For smoothing geometries, CatSmoothing uses the
centripetal Catmull-Rom spline algorithm, i.e., alpha=0.5. There are two functions
that can be used for smoothing geometries: smooth_linestrings and smooth_polygon.
There is also a function for computing tangent angles (in radians) at each vertex of a
line.
Basic Usage¶
For fitting a Catmull-Rom spline to a line, we can use the following code:
from catsmoothing import CatmullRom
verts = [(0, 0), (0, 0.5), (1.5, 1.5), (1.6, 1.5), (3, 0.2), (3, 0)]
n_pts = 15
smoothed = {}
for alpha in (0, 0.5, 1):
s = CatmullRom(verts, alpha=alpha, bc_type="closed")
dots = int((s.grid[-1] - s.grid[0]) * n_pts) + 1
distances = s.grid[0] + np.arange(dots) / n_pts
smoothed[alpha] = s.evaluate(distances)

For smoothing a geometry, we can use the following code:
from shapely import Polygon
import catsmoothing as cs
poly = Polygon(verts)
ploy_smoothed = cs.smooth_polygon(poly, n_pts=50)

For smoothing a noisy line, we can use the following code:
import numpy as np
from shapely import LineString
import catsmoothing as cs
rng = np.random.default_rng(123)
x = np.linspace(-3, 2.5, 50)
y = np.exp(-(x**2)) + 0.1 * rng.standard_normal(50)
line = LineString(np.c_[x, y])
line_smoothed = cs.smooth_linestrings(line, n_pts=30, gaussian_sigmas=2)

We can then compute the tangent angles in radians at each vertex of the smoothed line:

Pre-smoothing and continuity options¶
The smoothing functions and CatmullRom accept keyword-only options:
sigma_units="length"measures the Gaussian sigma in coordinate units along the line, so unevenly spaced vertices are smoothed evenly.taubin_iterations=napplies Taubin smoothing, which damps jitter and keeps the size of curves drawn with more than about a dozen vertices per turn (Gaussian smoothing shrinks closed rings).continuity="g2"makes curvature continuous, andcontinuity="c2"also makes the second derivative continuous; vertices and their tangents are unchanged.
line_smoothed = cs.smooth_linestrings(
line, distances=0.1, gaussian_sigmas=0.3, sigma_units="length", continuity="g2"
)
For more examples, visit the documentation.
Contributing¶
We welcome contributions! For guidelines, please refer to the contributing guide and CODE_OF_CONDUCT.md.
License¶
CatSmoothing is licensed under the MIT License. See the LICENSE file for details.