Bezier-rs

Computational geometry algorithms for Bezier curves and paths, purpose-built for 2D graphics engines.

Library
Cargo
v0.5.0
19stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
20/100Needs Attention
Development Activity0
Maintenance0
Community24
Maturity36
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture80
Code Quality78
Innovation62
Learning Curve70

Bezier-rs is a Rust crate implementing computational geometry algorithms for Bezier segments and multi-segment paths (subpaths). It was extracted from Graphite, an open-source 2D vector graphics editor, where it powered curve rendering, intersection testing, and path manipulation.

The crate models curves as Bezier structs (linear, quadratic, or cubic, distinguished by their BezierHandles variant) and paths as Subpath structs composed of manipulator groups with anchor and handle points. On top of these types it implements a substantial algorithm library: de Casteljau subdivision, tangents and normals, curvature, arc-length parametrization, bounding boxes, self-intersection and curve-curve intersection detection, curve-to-circular-arc approximation, offsetting, and winding number calculation.

The project is archived and no longer under active development — Graphite has since migrated to the Kurbo crate for better performance and correctness — but Bezier-rs remains available on crates.io and implements several algorithms (notably arc approximation and some intersection routines) that Kurbo does not yet cover, making it a useful reference or drop-in for projects that need those specific operations.

What You Get

  • Bezier and Subpath types representing linear, quadratic, and cubic curves and multi-segment anchor/handle paths
  • Curve construction helpers: from coordinates, from points with a fitting t value, or through-point interpolation
  • Geometric queries: tangents, normals, curvature, local extrema, inflection points, and axis-aligned bounding boxes
  • Intersection algorithms: curve-curve intersections, self-intersections, line/ray crossing tests, and rectangle intersections
  • Circular-arc approximation with configurable strategy (greedy, divide-and-conquer, or automatic fallback) and error tolerance
  • SVG export helpers (to_svg, curve_to_svg) for visualizing curves, anchors, and handle lines directly
  • Optional serde feature for serializing curve and path types, and a kurbo interop feature

Common Use Cases

  • Implementing curve rendering and editing in a 2D vector graphics or illustration application
  • Computing precise curve-curve or curve-shape intersections for hit-testing or boolean path operations
  • Approximating Bezier curves with circular arcs for renderers or plotters that only support arc primitives
  • Calculating arc-length parametrization for animating an object at constant speed along a curve
  • Generating SVG path debug visualizations of curve geometry during development

Under The Hood

Architecture The crate is organized as two parallel type hierarchies — bezier/ for single curve segments and subpath/ for multi-segment paths built from ManipulatorGroup anchor/handle triples — each split into core, structs, manipulators, lookup, solvers, and transform submodules with mod.rs re-exporting a flat public API via lib.rs. This is a value-oriented, dependency-free design: Bezier and Subpath are plain structs manipulated through method impls spread across the submodules by responsibility (construction in core, point/geometry queries in lookup, algorithmic operations like intersections and arcs in solvers), rather than through traits or dynamic dispatch. Supporting modules (polynomial.rs, poisson_disk.rs, consts.rs, utils.rs) provide shared numerical primitives — a generic const-sized Polynomial<N> type, Poisson-disk sampling, and TValue/SubpathTValue enums that unify parametric and euclidean curve-position addressing across both Bezier and Subpath. Because algorithms operate purely on these value types with no external state, changing the core BezierHandles/ManipulatorGroup representations would ripple through nearly every solver function, but the layered module split keeps that blast radius legible.

Tech Stack The crate targets Rust edition 2024 (rust-version 1.85) and depends on glam 0.29 for DVec2/DMat2 vector and matrix math, plus a small poly-cool dependency; serde and kurbo interop are gated behind optional features. There is no runtime, framework, or I/O dependency — it’s a pure computation library. The repository also ships an interactive-docs/ subproject (Vite + TypeScript + a Rust/WASM crate) that compiles the library to WebAssembly to power a live, graphical API documentation site hosted via a separate GitHub Actions deploy workflow.

Code Quality The crate has 113 #[test]-annotated unit tests embedded alongside implementation code (notably in solvers.rs and the corresponding subpath modules), plus a dedicated compare.rs module of floating-point-tolerant comparison helpers (compare_points, compare_f64s) used throughout the test suite to handle geometric floating-point error. CI (tests.yml) runs cargo fmt --all --check and cargo test --all-features on every push and PR, and a rustfmt.toml pins consistent formatting (tabs, specific width rules). Public API surface is documented extensively with doc comments explaining parameter semantics (e.g. the TValue enum’s parametric-vs-euclidean distinction) and links to external references like Pomax’s Bezier curve primer, though the crate itself acknowledges its algorithms are “naive and unoptimized” relative to its successor, Kurbo.

What Makes It Unique Bezier-rs’s most distinctive design choice is being anchor-centric rather than segment-centric: paths are defined by anchor points with incoming/outgoing handles (matching how design tools like Graphite model paths) rather than by a sequence of move-to/line-to/curve-to commands as SVG and Kurbo do — a representation better suited to interactive path editing than to rendering pipelines. It also implements several algorithms not commonly bundled together in one crate, particularly configurable circular-arc approximation with automatic fallback between a greedy and divide-and-conquer strategy, and curve self-intersection detection — capabilities the project’s own README notes are still missing from its now-preferred successor Kurbo.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search