Types & Utilities¶
Core types used throughout PyFreeform, plus utility functions for common operations.
Coord
dataclass
¶
An immutable 2D coordinate with math operations.
Coords are the foundation of all positioning in PyFreeform. They support arithmetic operations and common geometric calculations.
Attributes:
| Name | Type | Description |
|---|---|---|
x |
float
|
Horizontal coordinate |
y |
float
|
Vertical coordinate |
Example
lerp ¶
Linear interpolation between this coord and another.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
Coord
|
The target coord. |
required |
t
|
float
|
Interpolation factor (0 = self, 1 = other). Values outside 0-1 extrapolate beyond the coords. |
required |
Returns:
| Type | Description |
|---|---|
Coord
|
The interpolated coord. |
rotated ¶
Supports arithmetic — addition, subtraction, scalar multiply/divide, negation:
a = Coord(100, 200)
b = Coord(50, 50)
a + b # Coord(150, 250)
a - b # Coord(50, 150)
a * 2 # Coord(200, 400)
a / 2 # Coord(50.0, 100.0)
-a # Coord(-100, -200)
a[0], a[1] # 100, 200 (subscript access)
RelCoord
dataclass
¶
An immutable 2D relative coordinate (fractions 0.0-1.0).
Used for positioning within surfaces. (0, 0) is top-left, (1, 1) is bottom-right.
Fields are named rx and ry to prevent confusion with pixel Coord(x, y).
Fields are rx, ry (not x, y) to distinguish from pixel Coord. Supports the same arithmetic as Coord:
a = RelCoord(0.2, 0.3)
b = RelCoord(0.1, 0.1)
a + b # RelCoord(0.3, 0.4)
a - b # RelCoord(0.1, 0.2)
a * 2 # RelCoord(0.4, 0.6)
rx, ry = a # destructuring works
Where RelCoord Appears¶
| API | Usage |
|---|---|
entity.at |
Returns RelCoord (or None if in absolute mode) |
add_*(..., at=) |
Accepts RelCoord, plain tuple, or named position string |
cell.normalized_position |
Returns RelCoord (cell position within grid, 0.0–1.0) |
Plain tuples work too
All APIs that accept RelCoord also accept plain (rx, ry) tuples. Returned values are RelCoord instances with named fields and helper methods.
AnchorSpec¶
AnchorSpec is the type accepted by entity.anchor(), surface.anchor(), and the start_anchor/end_anchor parameters of connect(). It unifies three forms:
| Form | Example | Description |
|---|---|---|
str |
"center", "top_right", "v0" |
Named anchor (entity-specific) |
tuple[float, float] |
(0.7, 0.3) |
Relative coordinate within bounding box |
RelCoord |
RelCoord(0.7, 0.3) |
Same as tuple, with named fields |
For entities, tuples/RelCoords resolve against the axis-aligned bounding box. Rect overrides this to use local coordinate space (rotation-aware). For surfaces, they resolve against the surface's rectangular region.
rect.anchor("top_right") # Named anchor
rect.anchor((0.7, 0.3)) # 70% across, 30% down
dot.connect(rect, end_anchor="left") # In connections
PaintLike¶
PaintLike = ColorLike | Gradient — the union type for all fill=, color=, and stroke= parameters. Accepts any solid color or gradient object.
Image ¶
An image composed of multiple layers.
Each layer represents a channel of the image (red, green, blue, alpha) or a computed property (brightness, grayscale). Layers are created lazily when accessed.
Attributes:
| Name | Type | Description |
|---|---|---|
width |
int
|
Image width in pixels |
height |
int
|
Image height in pixels |
layers |
dict[str, Layer]
|
Dictionary of layer name to Layer object |
Example
Create an image from channel arrays.
Use Image.load() to create from a file instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
red
|
ndarray
|
Red channel as 2D numpy array (0-255). |
required |
green
|
ndarray
|
Green channel as 2D numpy array (0-255). |
required |
blue
|
ndarray
|
Blue channel as 2D numpy array (0-255). |
required |
alpha
|
ndarray | None
|
Optional alpha channel as 2D numpy array (0-255). |
None
|
load
classmethod
¶
load(path: str | Path, frame: int = 0) -> Image
Load an image from a file.
Supports PNG, JPEG, GIF, WebP, BMP, TIFF, and other formats supported by Pillow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to the image file. |
required |
frame
|
int
|
For animated images (GIF), which frame to load (default: 0). |
0
|
Returns:
| Type | Description |
|---|---|
Image
|
A new Image instance. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file doesn't exist. |
ValueError
|
If the file can't be decoded as an image. |
from_pil
classmethod
¶
from_pil(pil_img: Image) -> Image
Create an Image from a PIL Image object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pil_img
|
Image
|
A PIL Image object. |
required |
Returns:
| Type | Description |
|---|---|
Image
|
A new Image instance. |
rgb_at ¶
Get RGB color at a position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
int
|
Horizontal position (0 = left). |
required |
y
|
int
|
Vertical position (0 = top). |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, int]
|
Tuple of (red, green, blue) as integers 0-255. |
hex_at ¶
Get hex color string at a position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
int
|
Horizontal position (0 = left). |
required |
y
|
int
|
Vertical position (0 = top). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Color as "#rrggbb" string. |
rgba_at ¶
Get RGBA color at a position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
int
|
Horizontal position (0 = left). |
required |
y
|
int
|
Vertical position (0 = top). |
required |
Returns:
| Type | Description |
|---|---|
int
|
Tuple of (red, green, blue, alpha) as integers 0-255. |
int
|
If no alpha channel exists, alpha is 255. |
alpha_at ¶
Get alpha (opacity) at a position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
int
|
Horizontal position (0 = left). |
required |
y
|
int
|
Vertical position (0 = top). |
required |
Returns:
| Type | Description |
|---|---|
float
|
Alpha value as float 0.0-1.0 (0 = transparent, 1 = opaque). |
resize ¶
resize(width: int, height: int) -> Image
Resize to exact dimensions.
May distort aspect ratio. For aspect-preserving resize, use fit().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
int
|
Target width. |
required |
height
|
int
|
Target height. |
required |
Returns:
| Type | Description |
|---|---|
Image
|
A new Image with the specified dimensions. |
fit ¶
fit(width: int, height: int) -> Image
Resize to fit within bounds, preserving aspect ratio.
The result will be at most width x height, but may be smaller in one dimension to maintain proportions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
int
|
Maximum width. |
required |
height
|
int
|
Maximum height. |
required |
Returns:
| Type | Description |
|---|---|
Image
|
A new Image that fits within the bounds. |
quantize ¶
quantize(cols: int | None = None, rows: int | None = None) -> Image
Resize to a specific grid size.
Useful for creating dot art with a specific number of dots. If only cols or rows is specified, the other is calculated to maintain aspect ratio.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cols
|
int | None
|
Target number of columns (width in pixels). |
None
|
rows
|
int | None
|
Target number of rows (height in pixels). |
None
|
Returns:
| Type | Description |
|---|---|
Image
|
A new Image with the specified grid dimensions. |
See also
For image-to-art workflows, see Image to Art.
Layer ¶
A 2D matrix of values representing one channel of an image.
Layers are the building blocks of images in PyFreeform. Each layer holds a single channel of data (e.g., red, green, blue, alpha, brightness).
Attributes:
| Name | Type | Description |
|---|---|---|
data |
ndarray
|
The underlying numpy array |
width |
int
|
Matrix width (number of columns) |
height |
int
|
Matrix height (number of rows) |
Example
Create a layer from a numpy array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ndarray
|
A 2D numpy array of values. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If data is not 2-dimensional. |
A single-channel grayscale array. Access values with layer[x, y] (returns 0–255).
Utility Functions¶
map_range ¶
map_range(value: float, in_min: float = 0, in_max: float = 1, out_min: float = 0, out_max: float = 1, clamp: bool = False) -> float
Convert a value from one range to another.
Think of it like converting between units. If brightness goes from 0 to 1 but you want a radius between 2 and 10, this does the conversion for you:
radius = map_range(brightness, 0, 1, 2, 10)
# brightness 0.0 → radius 2
# brightness 0.5 → radius 6
# brightness 1.0 → radius 10
Swap the output range to reverse the direction:
radius = map_range(brightness, 0, 1, 10, 2)
# brightness 0.0 → radius 10 (dark = big)
# brightness 1.0 → radius 2 (bright = small)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
float
|
The input value to convert. |
required |
in_min
|
float
|
Start of the input range (default: 0). |
0
|
in_max
|
float
|
End of the input range (default: 1). |
1
|
out_min
|
float
|
Start of the output range (default: 0). |
0
|
out_max
|
float
|
End of the output range (default: 1). |
1
|
clamp
|
bool
|
If True, keep the result within the output range. |
False
|
radius = map_range(cell.brightness, 0, 1, 2, 10)
# brightness 0.0 → radius 2, brightness 1.0 → radius 10
# Swap output range to reverse direction
radius = map_range(cell.brightness, 0, 1, 10, 2) # dark = big, bright = small
apply_brightness ¶
Apply a brightness multiplier to a color.
Scales each RGB channel by brightness (0.0 = black, 1.0 = unchanged).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
color
|
ColorLike
|
Any supported color format (name, hex, or RGB tuple). |
required |
brightness
|
float
|
Multiplier from 0.0 (black) to 1.0 (unchanged). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Hex color string with brightness applied. |
apply_brightness("coral", 0.5) # Half-bright coral → "#7f3f28"
apply_brightness("white", 0.0) # Pure black → "#000000"
apply_brightness((255, 0, 0), 1) # Unchanged red → "#ff0000"
gray ¶
Create a grayscale color from a brightness value.
Shorthand for apply_brightness("white", brightness).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
brightness
|
float
|
0.0 (black) to 1.0 (white). |
required |
Returns:
| Type | Description |
|---|---|
str
|
Hex color string. |
get_angle_at ¶
Get tangent angle in degrees at parameter t along a path.
If path implements FullPathable, uses angle_at() directly.
Otherwise falls back to numeric differentiation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Pathable
|
Any Pathable object. |
required |
t
|
float
|
Parameter from 0.0 to 1.0. |
required |
epsilon
|
float
|
Step size for numeric differentiation. |
1e-05
|
Returns:
| Type | Description |
|---|---|
float
|
Angle in degrees (0 = rightward, 90 = downward in SVG coords). |
display ¶
Display utilities for PyFreeform.
display ¶
display(target: Scene | str | Path) -> None
Display an SVG in the default web browser.
Can display either a Scene (renders to temp file first) or an existing SVG file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Scene | str | Path
|
A Scene to render, or a path to an existing SVG file. |
required |