Geometry Primitives
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
Geometry primitives in guiltty provide the foundational building blocks for pixel-level 2D graphics within a terminal environment. These primitives range from basic coordinate structures like Point and Rect to complex drawable entities defined within the Shape enumeration. The system is designed to be backend-agnostic, allowing the core logic to define geometric relationships and rasterization strategies while delegating the final presentation to specific backends like guiltty-kitty.
These primitives are primarily utilized by the Canvas struct, which serves as a pixel buffer for drawing operations. The library supports a variety of shapes including lines, rectangles, circles, ellipses, triangles, and arbitrary paths. Each shape can be manipulated using specific fill strategies or stroke algorithms, ensuring precise positioning and rendering as described in the README.md.
Sources: crates/guiltty-core/src/lib.rs:1-10, README.md:1-15
Basic Primitives
The library defines several core data structures to handle positioning and sizing within the 2D coordinate space. These structures use i32 for coordinates and u32 for dimensions to allow for flexible positioning, including off-canvas coordinates.
Point
A Point represents a single pixel-addressable location with an origin at the top-left (0,0).
- Data Structure:
pub struct Point { pub x: i32, pub y: i32 } - Constructor:
Point::new(x, y)
Rect
A Rect defines a rectangular area in pixel space.
- Data Structure:
pub struct Rect { pub x: i32, pub y: i32, pub width: u32, pub height: u32 } - Constructor:
Rect::new(x, y, width, height)
Color
While not strictly a geometric shape, Color is the primitive value assigned to the pixels defined by geometry. It uses the RGBA8 model.
- Data Structure:
pub struct Color { pub r: u8, pub g: u8, pub b: u8, pub a: u8 } - Constructors:
Color::rgb(r, g, b)(defaults alpha to 255) orColor::rgba(r, g, b, a).
Sources: crates/guiltty-core/src/lib.rs:8-66
Complex Shapes
The Shape enum aggregates various geometric forms that can be rendered onto a Canvas.
| Shape Type | Parameters | Description |
|---|---|---|
Line | from: Point, to: Point | A single-pixel wide line segment. |
Rect | origin: Point, width: u32, height: u32 | A filled rectangle. |
Circle | center: Point, radius: u32 | A filled circle defined by a center and radius. |
Ellipse | center: Point, rx: u32, ry: u32 | A filled ellipse with independent X and Y radii. |
Triangle | a: Point, b: Point, c: Point | A filled triangle defined by three vertices. |
Path | points: Vec<Point>, closed: bool | Connected segments. Filled if closed; stroked if open. |
Sources: crates/guiltty-core/src/lib.rs:326-361
Rasterization and Algorithms
The guiltty-core module implements specific algorithms to convert geometric definitions into pixel data within the Canvas.
Line Rendering (Bresenham & Liang-Barsky)
Line segments are drawn using Bresenham's line algorithm. To optimize performance and prevent hangs when dealing with extreme coordinates (e.g., i32::MAX), lines are first processed through the Liang-Barsky clipping algorithm to restrict drawing to the visible canvas area.
Polygon Filling (Even-Odd Rule)
Closed paths and polygons are filled using a scanline fill algorithm implementing the even-odd rule. This approach handles concave and self-intersecting polygons by counting edge crossings for each scanline. To avoid ambiguity at vertices, scanlines are evaluated at y + 0.5.
Triangle Filling (Barycentric Test)
Triangles are rendered using a barycentric sign test. The algorithm scans only the bounding box of the triangle, intersected with the canvas bounds, and uses i128 arithmetic to prevent overflow during cross-product calculations.
Ellipse Filling
Ellipses and circles are rendered using an inclusion test: (dx/rx)^2 + (dy/ry)^2 <= 1.0. Calculations are performed in f64 to maintain precision for large radii where integer cross-multiplication might overflow u128.
Sources: crates/guiltty-core/src/lib.rs:388-535, tasks/plan.md:65-75
Logic Flow: Drawing a Shape
The following diagram illustrates the internal logic when Canvas::draw_shape is called.
The diagram shows how different shape variants trigger specific mathematical models and optimization steps (like clipping) before modifying the pixel buffer.
Sources: crates/guiltty-core/src/lib.rs:372-535
Geometric Relationships
The architecture maintains a strict hierarchy between the basic components and the rendering target.
This diagram represents the structural dependencies between coordinates (Point), geometric containers (Shape, Rect), and the entities that utilize them (Canvas, Sprite).
Sources: crates/guiltty-core/src/lib.rs:31-45, crates/guiltty-core/src/lib.rs:326-361, crates/guiltty-core/src/lib.rs:720-740
Conclusion
Geometry primitives in guiltty provide a robust and overflow-resistant foundation for terminal graphics. By combining standard geometric structures with optimized algorithms like Liang-Barsky clipping and Even-Odd scanline filling, the system ensures that complex shapes are rendered accurately and efficiently regardless of coordinate magnitude. These primitives enable the higher-level functionality of the library, such as movable sprites and text rendering, within a unified pixel-addressable framework.
Sources: crates/guiltty-core/src/lib.rs:1-10, tasks/plan.md:65-75