Skip to content

Transforms

All entities support non-destructive transforms — rotation and scale are stored as numbers and applied at render time via SVG transform, not baked into geometry. Transforms preserve relative bindings: rotating or scaling an entity that tracks a container-relative position does not destroy that binding.

See also

For hands-on transform examples, see Transforms and Layout.


Entity

Entity(x: float = 0, y: float = 0, z_index: int = 0)

Bases: ABC

Base class for all drawable objects in PyFreeform.

Entities are objects with identity - they can be moved, connected, and tracked. Unlike raw primitives, entities maintain relationships with other entities.

Attributes:

Name Type Description
position Coord

Current position (center point for most entities)

surface Surface | None

The surface containing this entity (Cell, Scene, or CellGroup)

connections Collection[Connection]

Connections involving this entity

Subclasses must implement
  • anchor(name): Return anchor point by name
  • anchor_names: Property listing available anchor names
  • to_svg(): Render to SVG element string

Initialize entity at position.

Parameters:

Name Type Description Default
x float

Initial x coordinate.

0
y float

Initial y coordinate.

0
z_index int

Layer ordering (higher = on top). Default 0.

0

rotation property writable

rotation: float

Rotation angle in degrees (accumulated, non-destructive).

scale_factor property writable

scale_factor: float

Scale factor (accumulated, non-destructive). Default 1.0.

rotation_center property

rotation_center: Coord

The center point for rotation and scaling transforms.

Default: entity position. Override for entities where the natural pivot differs (e.g., Rect center, Polygon centroid).

rotate

rotate(angle: float, origin: CoordLike | None = None) -> Entity

Rotate entity by angle degrees.

Without origin, rotates in place. With origin, also moves the entity around that point (like orbiting).

Parameters:

Name Type Description Default
angle float

Rotation in degrees (counterclockwise).

required
origin CoordLike | None

Point to rotate around. If None, rotates in place around the entity's natural center.

None

Returns:

Type Description
Entity

self, for method chaining.

scale

scale(factor: float, origin: CoordLike | None = None) -> Entity

Scale entity by factor.

Without origin, scales around the entity's natural center. With origin, also moves the entity toward/away from that point.

Parameters:

Name Type Description Default
factor float

Scale multiplier (1.0 = no change, 2.0 = double).

required
origin CoordLike | None

Point to scale around. If None, scales around the entity's natural center.

None

Returns:

Type Description
Entity

self, for method chaining.

fit_within

fit_within(target: Entity | tuple[float, float, float, float], scale: float = 1.0, recenter: bool = True, *, at: RelCoordLike | None = None, visual: bool = True, rotate: bool = False, match_aspect: bool = False) -> Entity

Scale and position entity to fit within another entity's inner bounds.

Parameters:

Name Type Description Default
target Entity | tuple[float, float, float, float]

Entity (uses inner_bounds()) or raw (min_x, min_y, max_x, max_y) tuple.

required
scale float

Fraction of target inner bounds to fill (0.0-1.0].

1.0
recenter bool

If True, center entity within target after scaling. Ignored when at is provided.

True
at RelCoordLike | None

Optional relative position (rx, ry) within the target's inner bounds, where (0,0) is top-left and (1,1) is bottom-right. Available space is constrained by the nearest edges so the entity never overflows.

None
visual bool

If True (default), include stroke width when measuring bounds so stroked entities don't overflow after fitting. Set to False for pure geometric fitting.

True
rotate bool

If True, find the rotation angle that maximizes how much of the target space the entity fills before scaling.

False
match_aspect bool

If True, rotate the entity so its bounding box aspect ratio matches the target's. Mutually exclusive with rotate.

False

Returns:

Type Description
Entity

self, for method chaining.

Example
dot = cell.add_dot(radius=0.5, color="navy")
label = cell.add_text("0.5", color="white", font_size=50)
label.fit_within(dot)
# Position in top-left of a rect's inner bounds:
label.fit_within(rect, at=(0.25, 0.25))

fit_to_surface

fit_to_surface(scale: float = 1.0, recenter: bool = True, *, at: RelCoordLike | None = None, visual: bool = True, rotate: bool = False, match_aspect: bool = False) -> Entity

Automatically scale and position entity to fit within its surface bounds.

Convenience wrapper around :meth:fit_within that uses the containing surface as the target region.

Parameters:

Name Type Description Default
scale float

Fraction of available space to fill (0.0-1.0). 1.0 = fill entire surface, 0.85 = use 85%.

1.0
recenter bool

If True, center entity in surface after scaling. Ignored when at is provided.

True
at RelCoordLike | None

RelCoordLike within the surface as (rx, ry) fractions. Constrains fitting to the space available at that point so the entity doesn't overflow. (0.5, 0.5) uses the full surface (default).

None
visual bool

If True (default), include stroke width in bounds measurement so stroked shapes don't overflow.

True
rotate bool

If True, auto-rotate to maximize surface coverage.

False
match_aspect bool

If True, rotate to match the surface's aspect ratio. Mutually exclusive with rotate.

False

Returns:

Type Description
Entity

self, for method chaining

Raises:

Type Description
ValueError

If entity has no surface, scale is out of range, or both rotate and match_aspect are True.

TypeError

If at is a string (named anchors sit on surface edges where available space is 0).

Example
ellipse = cell.add_ellipse(rx=2.0, ry=1.2, rotation=45)
ellipse.fit_to_surface(0.85)  # Auto-constrain to 85% of cell
dot = cell.add_dot(radius=0.8)
dot.fit_to_surface(1.0, at=(0.25, 0.25))  # Fit in top-left quadrant

Model-space vs world-space

  • Model-space properties (.radius, .width, .end, .vertices) are unchanged by transforms
  • World-space methods (anchor(), bounds(), point_at()) apply rotation and scale automatically
  • SVG output uses model-space coordinates with a transform attribute

Per-Entity Pivot Points

Each entity type defines its own natural rotation_center:

Entity Pivot
Dot, Ellipse, Text Center (position)
Rect Center of rectangle
Line, Curve Chord midpoint (start → end)
Polygon Centroid of vertices
Path Bezier midpoint at t=0.5
EntityGroup Accumulates in <g> transform (children unchanged)

Text fit_to_surface

For Text entities, fit_to_surface(fraction) adjusts font size (up or down) to fill the surface. Compare with add_text(fit=True) which only shrinks.