An open API service indexing awesome lists of open source software.

https://github.com/rupurt/txtplot

High-performance terminal plotting for Rust.
https://github.com/rupurt/txtplot

Last synced: about 1 month ago
JSON representation

High-performance terminal plotting for Rust.

Awesome Lists containing this project

README

          

# txtplot

High-performance terminal plotting for Rust.

`txtplot` renders mathematical plots, 3D visualizations, games, and complex terminal interfaces using Unicode Braille and block characters plus ANSI colors.

Unlike many TUI plotting libraries, `txtplot` is designed for speed: it uses flat contiguous buffers, renderer-specific cell encodings, clipping, and a zero-allocation rendering path to support real-time terminal graphics.

License: [MIT](LICENSE).

## Project Navigation

This repository carries a small set of foundational documents for users, contributors, and agents:

- [AGENTS.md](AGENTS.md) - implementation guidance for AI agents and contributors
- [CONSTITUTION.md](CONSTITUTION.md) - project principles, decision hierarchy, and compatibility posture
- [ARCHITECTURE.md](ARCHITECTURE.md) - module boundaries, data flow, and extension seams
- [GUIDE.md](GUIDE.md) - user guide for plots, 3D visuals, games, and terminal interfaces
- [CONFIGURATION.md](CONFIGURATION.md) - toolchain, shell, and API-level configuration surfaces
- [RELEASE.md](RELEASE.md) - release checklist and versioning process

If you use Nix, `nix develop` provides the Rust toolchain plus `cargo-nextest`, `just`, `keel`, and `sift`.

## Key Features

- High resolution: 8 sub-pixels per character (Braille 2x4). A 100x50 terminal yields a 200x200 effective pixel canvas.
- Pluggable cell renderers: Braille (`2x4`), HalfBlock (`1x2`), and Quadrant (`2x2`)
- Performance-oriented design:
- flat buffers for cache-friendly access
- zero-allocation rendering via `render_to`
- Cohen-Sutherland line clipping to discard off-screen geometry before rasterization
- Advanced pixel and color control:
- `unset_pixel` and `toggle_pixel`
- color blending modes with `Overwrite` and `KeepFirst`
- cell background colors for terminal panels and HUD-style layouts
- styled text with foreground, background, plus `Normal` / `Bold` / `Dim` intensity
- cell-space UI helpers with `text_screen()`, `text_screen_styled()`, `label_screen()`, and `panel_screen()`
- High-level chart aesthetics:
- `legend()`: automatic, opaque legend boxes with color markers
- `anchored_text()`: effortless label placement at `TopLeft`, `Center`, etc.
- opaque UI panels that clear underlying raster data for professional overlays
- Drawing primitives:
- lines, circles, polygons
- filled shapes via `rect_filled` and `circle_filled`
- text overlay support
- Ready-to-use charts:
- `scatter()`, `line_chart()`, `bar_chart()`, `pie_chart()`, `plot_function()`
- linear and `log10` axes through `AxisScale`
- Auto-range and axis helpers for chart setup
- Exported 3D building blocks in `txtplot::three_d`:
- `Vec3`, `Projection`, and `ZBuffer`
- screen projection helpers plus z-buffered raster helpers
- sphere, torus, and triangle mesh generators

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
txtplot = "0.1.0"
colored = "2.0"
```

## Quick Start

```rust
use colored::Color;
use txtplot::ChartContext;

fn main() {
let mut chart = ChartContext::new(60, 15);
chart.draw_grid(10, 4, Some(Color::BrightBlack));
chart.draw_axes((0.0, 10.0), (-1.5, 1.5), Some(Color::White));
chart.plot_function(|x: f64| x.sin(), 0.0, 10.0, Some(Color::Cyan));
chart.plot_function(
|x: f64| (x * 0.5).cos() * 0.5,
0.0,
10.0,
Some(Color::Magenta),
);
chart.text("sin(x)", 0.75, 0.85, Some(Color::Cyan));
chart.text("0.5*cos(0.5x)", 0.56, 0.10, Some(Color::Magenta));

println!("{}", chart.canvas.render());
}
```

### Styled Text Labels

Use `text_styled()` or the screen-space styled text helpers when you need label emphasis without changing the label content:

```rust
use colored::Color;
use txtplot::{ChartContext, TextStyle};

fn main() {
let mut chart = ChartContext::new(40, 10);
chart.text_styled(
"core-node",
0.45,
0.75,
TextStyle::new().with_foreground(Color::BrightWhite).bold(),
);
chart.text_styled(
"outer-node",
0.55,
0.30,
TextStyle::new().with_foreground(Color::BrightBlack).dim(),
);

println!("{}", chart.canvas.render());
}
```

### Anchored Text and Legends

Place labels and legends effortlessly using `ChartAnchor` without calculating pixel offsets:

```rust
use colored::Color;
use txtplot::{ChartAnchor, ChartContext, TextStyle};

fn main() {
let mut chart = ChartContext::new(60, 15);
chart.plot_function(|x| x.sin(), 0.0, 10.0, Some(Color::Cyan));

// Place a legend in the top right
let entries = [("Sine Wave", TextStyle::new().with_foreground(Color::Cyan))];
chart.legend(ChartAnchor::TopRight, &entries);

// Anchor a title or status label
chart.anchored_text_styled(
"LIVE MONITOR",
ChartAnchor::TopLeft,
TextStyle::new().with_foreground(Color::Yellow).bold(),
);

println!("{}", chart.canvas.render());
}
```

### Logarithmic Axes

```rust
use colored::Color;
use txtplot::{AxisScale, ChartContext};

fn main() {
let mut chart = ChartContext::new(60, 15);
chart.set_scales(AxisScale::Linear, AxisScale::Log10);

let points = vec![(1.0, 1.0), (2.0, 10.0), (3.0, 100.0), (4.0, 1000.0)];
let (range_x, range_y) = ChartContext::get_auto_range_scaled(
&points,
0.05,
AxisScale::Linear,
AxisScale::Log10,
);

chart.draw_axes(range_x, range_y, Some(Color::White));
chart.line_chart(&points, Some(Color::Cyan));
println!("{}", chart.canvas.render());
}
```

### Zero-Allocation Render Loop

If you are building a real-time app, avoid `render()` and use `render_to()`:

```rust
use std::fmt;
use colored::Color;
use txtplot::ChartContext;

fn main() -> fmt::Result {
let mut chart = ChartContext::new(60, 15);
chart.draw_axes((0.0, 10.0), (-1.0, 1.0), Some(Color::White));
chart.plot_function(|x: f64| x.sin(), 0.0, 10.0, Some(Color::Cyan));

let mut buffer = String::with_capacity(8000);
chart.canvas.render_to(&mut buffer, true, Some("60 FPS UI"))?;
print!("{buffer}");
Ok(())
}
```

### Renderer Showcase

Braille remains the default renderer, and `HalfBlockCanvas` / `HalfBlockChartContext` plus `QuadrantCanvas` / `QuadrantChartContext` provide alternate encodings. The showcase example renders the same chart and raster scene through all three renderers:

```bash
cargo run --release --example renderer_showcase
```

### Runtime Renderer Selection

If you want to choose a renderer from CLI or config input while still constructing a concrete generic chart or canvas, use `RendererKind` together with `with_renderer!`:

```bash
cargo run --release --example runtime_renderer -- halfblock
```

### 3D Surface Example

`txtplot` does not ship a full scene graph, but it now exports reusable 3D math, projection, and z-buffer helpers under `txtplot::three_d`. The surface example projects a volatility mesh into terminal pixels, uses a z-buffer for occlusion, and overlays a gradient-ascent path:

```bash
cargo run --release --example vol_surface
```

### t-SNE and Nearest-Neighbor Graph

The examples also include a small self-contained manifold-learning demo: it builds clustered 6D data, runs a lightweight t-SNE embedding, and overlays the original-space 3-nearest-neighbor graph on top of the 2D layout.

```bash
cargo run --release --example tsne_neighbors
```

## Coordinate System and Pixel API

To avoid mathematical confusion, `txtplot` offers two coordinate modes and multiple pixel operators:

| Coordinate Mode | Origin (0,0) | Y Direction | Best For |
| --- | --- | --- | --- |
| Cartesian | Bottom-left | Grows up | Math plots, functions, charts |
| Screen | Top-left | Grows down | UI, games, sprites, 3D projections |

Pixel manipulation methods:

- `set_pixel / set_pixel_screen`: turn a dot on
- `unset_pixel / unset_pixel_screen`: turn a dot off
- `toggle_pixel_screen`: flip the current state of a dot

Cell-space HUD methods:

- `text_screen`: write text in top-left screen coordinates
- `label_screen`: write text with per-cell background styling
- `panel_screen`: draw boxed UI regions for dashboards and overlays

## Demo Output

The following block is captured from `cargo run --example demo` using the built-in `render_no_color` path:

```text
A) Plain Render (render_no_color):
⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀
⠀⠀⠈⠉⠢⢄⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⡠⠔⠉⠁⠀⠀
⠀⠀⠀⠀⠀⠀⠑⢄⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠜⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠱⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢀⠜⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⡗⠒⠈⢆⠒⠒⠒⠒⠒⠒⠒⠒⡗⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⡗⠒⠒⠒⠒⠒⠒⠒⡠⠃⠒⠒⡗⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒⠒
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠣⡀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠘⢄⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⢠⠊⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⢀⠔⠁⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠘⢄⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠢⢄⡀⠀⠀⠀⠀⢀⡠⠔⠉⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
```

## Examples and Demos

The repository includes advanced examples and demos:

1. Function and chart gallery

```bash
cargo run --example demo
```

2. Primitive shapes and blending

```bash
cargo run --release --example primitives_demo
```

3. 3D volatility surface with gradient ascent

```bash
cargo run --release --example vol_surface
```

4. Braille, half-block, and quadrant renderer showcase

```bash
cargo run --release --example renderer_showcase
```

5. Runtime renderer selection from CLI input

```bash
cargo run --release --example runtime_renderer -- quadrant
```

6. t-SNE embedding with nearest-neighbor graph

```bash
cargo run --release --example tsne_neighbors
```

7. 3D gallery with camera, z-buffer, and zoom

```bash
cargo run --release --example 3dengine
```

8. Solar system Kepler 3D

```bash
cargo run --release --example solarsystem_kepler
```

9. Sprite engine

```bash
cargo run --release --example sprite_demo
```

10. Interactive fractals

```bash
cargo run --release --example fractalmove
```

## Performance

`txtplot` is optimized for real-time terminal rendering.

In a benchmark with a 236x104 sub-pixel canvas filled with trigonometric noise and particles on a modern machine:

- Debug mode: about 60 FPS
- Release mode: about 1600+ FPS

Use `just bench` or `cargo bench --bench canvas_benchmark` to run the current Criterion suite. It now includes renderer comparison groups for chart-heavy and raster-heavy scenes across Braille, HalfBlock, and Quadrant output.

## Roadmap

Detailed implementation planning now lives in `ARCHITECTURE.md`. The list below is only the user-facing summary.

- [x] Flat contiguous buffers for memory efficiency
- [x] Explicit coordinate APIs for screen and cartesian modes
- [x] Cohen-Sutherland line clipping
- [x] Zero-allocation rendering via `render_to`
- [x] Filled primitives and erasers
- [x] Color blending policies
- [x] Logarithmic scaling support
- [ ] Automatic legend box
- [x] Trait-based pluggable terminal renderers
- [x] Runtime renderer selection helpers

## License

This project is licensed under the [MIT License](LICENSE).