AgentSkillsCN

kurbo-api

当您编写使用 kurbo 进行 2D 几何、曲线、路径、形状或仿射变换的 Rust 代码时,可选用此方案。无论是在 kurbo 代码库中工作,还是在依赖 kurbo 的各类项目中,此方案皆适用。

SKILL.md
--- frontmatter
name: kurbo-api
description: Use when writing Rust code that uses kurbo for 2D geometry, curves, paths, shapes, or affine transformations. Use when working in the kurbo codebase or any project depending on kurbo.

Kurbo API Reference

Overview

Kurbo ("curve" in Esperanto) is a Rust 2D curves library for vector graphics and computational geometry. It provides high-accuracy curve primitives, path operations, and affine transformations.

Core Types

Basic Geometry

TypeDescription
Point2D point (f64 coords), arithmetic with Vec2
Vec22D vector with dot/cross, normalize, rotate
RectRectangle (min/max), union/intersection
SizeWidth/height
InsetsPadding/margins

Curves

TypeDescription
LineLine segment between two points
QuadBezQuadratic Bézier (1 control point)
CubicBezCubic Bézier (2 control points)
ArcElliptical arc with SVG-style params

Shapes

TypeDescription
CircleCenter + radius
EllipseRotated ellipse
RectAlso a shape
RoundedRectRectangle with corner radii
TriangleThree vertices

Paths

TypeDescription
BezPathVector of PathEl, multiple subpaths
PathElMoveTo, LineTo, QuadTo, CurveTo, ClosePath
PathSegLine, Quad, or Cubic segment

Transforms

TypeDescription
Affine2D affine matrix (scale, rotate, translate, skew)
TranslateScaleSimple translate + uniform scale

Key Traits

Shape Trait

All shapes implement this:

rust
shape.path_elements(tolerance)  // Iterator, no allocation
shape.to_path(tolerance)        // Allocates BezPath
shape.area()                    // Signed area
shape.perimeter(tolerance)      // Total length
shape.winding(point)            // Winding number
shape.contains(point)           // Point-in-shape (non-zero rule)
shape.bounding_box()            // Axis-aligned Rect

ParamCurve Traits

Curves (Line, QuadBez, CubicBez, Arc) implement:

rust
curve.eval(t)                   // Point at parameter t ∈ [0,1]
curve.subsegment(t0..t1)        // Extract portion
curve.start() / curve.end()     // Endpoints
curve.arclen(accuracy)          // Arc length
curve.inv_arclen(s, accuracy)   // Parameter at arc length s
curve.nearest(point, accuracy)  // Nearest point info
curve.curvature(t)              // Curvature at t
curve.extrema()                 // Parameter values of extrema
curve.bounding_box()            // Tight bounding box

Common Patterns

Creating Shapes

rust
let circle = Circle::new((100.0, 100.0), 50.0);
let rect = Rect::new(0.0, 0.0, 100.0, 50.0);
let ellipse = Ellipse::new((0.0, 0.0), (100.0, 50.0), 0.0);
let rounded = RoundedRect::new(0.0, 0.0, 100.0, 50.0, 10.0);

Building Paths

rust
let mut path = BezPath::new();
path.move_to((0.0, 0.0));
path.line_to((100.0, 0.0));
path.quad_to((150.0, 50.0), (100.0, 100.0));
path.curve_to((50.0, 150.0), (0.0, 150.0), (0.0, 100.0));
path.close_path();

Transformations

rust
// Chain transformations (applied left-to-right)
let affine = Affine::translate((10.0, 20.0))
    .then_rotate(PI / 4.0)
    .then_scale(2.0);

// Apply to geometry
let new_point = affine * point;
let new_path = affine * &path;

// Other transforms
Affine::rotate(angle)
Affine::rotate_about(angle, center)
Affine::scale(s)
Affine::scale_non_uniform(sx, sy)
Affine::skew(kx, ky)
Affine::reflect(point, direction)

Shape to Path Conversion

rust
// With allocation
let path: BezPath = circle.to_path(0.1);

// Without allocation (iterator)
for el in circle.path_elements(0.1) {
    match el {
        PathEl::MoveTo(p) => {},
        PathEl::LineTo(p) => {},
        PathEl::QuadTo(c, p) => {},
        PathEl::CurveTo(c1, c2, p) => {},
        PathEl::ClosePath => {},
    }
}

Iterating Path Segments

rust
// As segments (Line/Quad/Cubic)
for seg in path.segments() {
    match seg {
        PathSeg::Line(line) => {},
        PathSeg::Quad(quad) => {},
        PathSeg::Cubic(cubic) => {},
    }
}

Stroking

rust
use kurbo::{Stroke, StrokeOpts, Cap, Join, stroke};

let style = Stroke::new(5.0)
    .with_caps(Cap::Round)
    .with_join(Join::Miter)
    .with_miter_limit(4.0)
    .with_dashes(0.0, [10.0, 5.0]);  // dash offset, pattern

let stroked = stroke(path, &style, &StrokeOpts::default(), 0.25);

SVG Interop

rust
// Path to SVG string
let svg_str = path.to_svg();

// SVG string to path
let path: BezPath = BezPath::from_svg("M0,0 L100,0 Q150,50 100,100 Z").unwrap();

Curve Operations

rust
let cubic = CubicBez::new((0,0), (30,50), (70,50), (100,0));

// Evaluate
let midpoint = cubic.eval(0.5);

// Split
let (first_half, second_half) = cubic.subdivide();

// Arc length
let len = cubic.arclen(1e-9);

// Find nearest point
let nearest = cubic.nearest(test_point, 1e-9);
// nearest.distance_sq, nearest.t

// Curvature
let k = cubic.curvature(0.5);

Accuracy Parameters

Many functions take an accuracy or tolerance parameter:

  • tolerance: Maximum allowed error in path approximation (e.g., 0.1 for curves to lines)
  • accuracy: Target precision for numerical methods (e.g., 1e-9 for arc length)

Smaller values = higher accuracy = more computation.

Feature Flags

toml
[dependencies]
kurbo = { version = "0.11", features = ["serde"] }
FeatureDescription
std(default) Standard library
libmFor no_std environments
serdeSerialization support
schemarsJSON schema generation
mintmint type conversions
euclideuclid type conversions

Common Mistakes

MistakeFix
Forgetting tolerance paramAll path_elements/to_path calls need tolerance
Wrong winding for holesHoles need opposite winding direction
Ignoring accuracy paramUse 1e-6 to 1e-9 for precision-critical code
Mutating paths during iterationCollect changes, apply after