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.
- Host: GitHub
- URL: https://github.com/rupurt/txtplot
- Owner: rupurt
- License: mit
- Created: 2026-03-12T11:39:02.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-12T17:04:27.000Z (4 months ago)
- Last Synced: 2026-03-12T17:53:15.606Z (4 months ago)
- Language: Rust
- Homepage:
- Size: 114 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
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).