circles-sketch 0.2.2

Generate interactive Fourier epicycle animations from contours, text, or SVG files
Documentation

circles-sketch

A Rust tool that reads 2D contours from YAML files, text strings, or SVG files, computes their complex Fourier decomposition, and generates interactive HTML visualizations with animated epicycles.

crates.io

Install

cargo install circles-sketch

Live demos

How it works

Any closed 2D shape can be described as a sum of rotating circles (Fourier series). This tool:

  1. Reads a contour from one of three input sources (YAML points, text string, SVG file)
  2. Interpolates the contour to N evenly-spaced points (default 1000, configurable with -n)
  3. Computes the complex Discrete Fourier Transform (DFT)
  4. Generates two self-contained HTML files: a full interactive page and a minimal embed version

The animation shows epicycles (rotating circles) that, when chained together, trace out the original shape. As more harmonics are added, the approximation gets closer to the original contour.

graph LR
    subgraph Inputs
        YAML["YAML points<br/><i>guitar.yml</i>"]
        TEXT["Text + Font<br/><i>'Hello' + Arial</i>"]
        SVG["SVG file<br/><i>band.svg</i>"]
        CFG["Config YAML<br/><i>*-config.yml</i>"]
    end

    YAML -->|serde_yaml::from_str| C["Contour<br/>Vec&lt;(f64,f64)&gt;"]
    TEXT -->|svg_path_of_text| SP["SVG path string"]
    SVG -->|extract &lt;path&gt; d=| SP
    SP -->|points_of_svg_path| C

    C -->|"interpolate(n)"| IC["Interpolated<br/>Contour"]
    IC -->|svg_path_of_contour| SVGPath["SVG path"]
    IC -->|fourier_decomposition| FD["Fourier<br/>Coefficients"]

    SVGPath --> GEN["html_of_svg_path_with_fourier<br/>embed_html_of_svg_path_with_fourier"]
    FD --> GEN
    CFG -->|EmbedOptions| GEN

    subgraph Output
        HTML["stem.html<br/><i>Full interactive page</i>"]
        EMBED["stem-embed.html<br/><i>Minimal embed</i>"]
    end

    GEN --> HTML
    GEN --> EMBED

    style YAML fill:#4a9eff,color:#fff
    style TEXT fill:#4a9eff,color:#fff
    style SVG fill:#4a9eff,color:#fff
    style CFG fill:#f5a623,color:#fff
    style C fill:#7b68ee,color:#fff
    style SP fill:#7b68ee,color:#fff
    style IC fill:#7b68ee,color:#fff
    style SVGPath fill:#7b68ee,color:#fff
    style FD fill:#7b68ee,color:#fff
    style GEN fill:#e06c75,color:#fff
    style HTML fill:#50c878,color:#fff
    style EMBED fill:#50c878,color:#fff

CLI

The tool uses subcommands for different input types:

From YAML points

circles-sketch points examples/guitar.yml
open examples/guitar.html

Reads guitar.yml and the matching config guitar-config.yml, producing guitar.html and guitar-embed.html.

From text

circles-sketch text --font "TimesNewRomanPSMT" "Hello World"
open hello-world.html

Renders text using a system font and generates the visualization. Use list-fonts to find available font PostScript names:

circles-sketch list-fonts

From SVG

circles-sketch --flip-y svg examples/band.svg
open examples/band.html

Extracts <path> data from an SVG file. Supports absolute and relative M, L, C, Q, H, V, Z commands with bezier curve sampling. Use --flip-y for SVGs with negative Y scale transforms.

Generate default config

circles-sketch init-config my-config.yml

Global options

  • --config <file> — specify a config YAML
  • -o <stem> — set the output file stem
  • -n <N> / --num-points <N> — number of interpolation points (default: 1000)
  • --flip-y — flip Y coordinates (for SVGs with negative Y scale transforms)

Config format

The config file controls animation behavior and display options:

speed: 3.0
steps:
  thresholds:
  - start: 10
    step: 1
  - start: 20
    step: 5
  - start: 100
    step: 10
  max_harmonic: 100
show_contour: Never          # Always, Never, or !OnceEvery {modulo: N, remainders: [0]}
show_point: true
show_trace: Always
trace_length: 0.5
opacity: 0.5
show_nh: true
trace_width: 1.0
contour_width: 1.0
show_fourier_circles: Always
trace_colors:
- red
- lime
- dodgerblue
- gold
- hotpink
- cyan
- orange

Harmonic steps

The steps field controls how harmonics progress across animation loops. The format thresholds + max_harmonic works as follows:

  • Start at nh = first threshold's start, with increment = first threshold's step
  • At each loop, nh += increment
  • When nh >= next threshold's start, increment changes to that threshold's step
  • When nh >= max_harmonic, stop

For example, with thresholds [(10, 1), (20, 5), (100, 10)] and max_harmonic: 1000:

  • nh = 10, 11, 12, ..., 19 (increment 1)
  • nh = 20, 25, 30, ..., 95 (increment 5)
  • nh = 100, 110, 120, ..., 1000 (increment 10)

The steps schedule is editable in the interactive HTML page using the format 10 1 ; 20 5 ; 100 10 ; 1000.

Show modes

Fields show_contour, show_trace, and show_fourier_circles accept:

  • Always — show on every loop
  • Never — never show
  • !OnceEvery {modulo: N, remainders: [r1, r2, ...]} — show when loop_index % N is in the remainders list

Interactive controls

The generated full HTML page includes:

  • t slider — scrub through the parametric position on the contour
  • Loop display — current loop index and harmonic count
  • Start / Stop — animate the drawing
  • Speed slider — control animation speed
  • Harmonics loop — editable harmonic step schedule (start step ; start step ; ... ; max)
  • Contour / Trace / Circles — select Always, Never, or Every N (with modulo and remainders)
  • Point — toggle the drawing position indicator
  • NH label — toggle the harmonic count label on the SVG
  • Opacity — trace opacity
  • Trace length — fraction of the contour retained in the trace
  • Trace width / Contour width — stroke widths

YAML points format

Contour files are simple YAML with a list of [x, y] points:

points:
  - [0.0, 0.0]
  - [1.0, 0.0]
  - [1.0, 1.0]
  - [0.0, 0.0]

Examples

File Description
examples/square.yml Simple square
examples/cardioid.yml Cardioid curve
examples/move-the-line "Move The Line" text (AkayaTelivigala font)
examples/note.yml Music note symbol
examples/guitar.yml Electric guitar
examples/band.svg Band silhouette (SVG input)

Project structure

src/
  lib.rs          — Library crate root
  contour.rs      — Contour, ContourFunction, Fourier decomposition
  model.rs        — EmbedOptions, HarmonicSteps, WhenToShow config types
  svg.rs          — SVG path parsing, HTML generation
  text.rs         — Text-to-SVG-path using system fonts
  test.rs         — Unit tests
  bin/
    circles-sketch.rs — CLI binary (clap subcommands)
examples/
  *.yml           — Contour data files
  *-config.yml    — Config files
  *.html          — Generated full interactive pages
  *-embed.html    — Generated minimal embed pages

Building

cargo build
cargo test

Dependencies

  • clap — CLI argument parsing with subcommands
  • serde + serde_yaml — YAML serialization/deserialization
  • ttf-parser — Font glyph outline extraction
  • font-kit — System font lookup