tituli.geometry¶
Boxes, anchors, safe areas and parametric paths — the coordinate vocabulary.
Two coordinate systems, deliberately:
normalised
(x, y, w, h)in0..1of the frame, top-left origin — the resolution-independent form used by specs, byburns.salient_boxand by the lacing body. This is what a request is written in.pixel
Box(x0, y0, x1, y1)floats — what layout and rendering compute in once aFramesize is known.
A Path is a curve you can lay glyphs along: point(s) and angle(s)
by arc length. Constructors cover lines, arcs, waves, Béziers, polylines and SVG
d strings, which is what lets a calligram be any shape rather than a
hard-coded sine.
>>> b = Box(10, 20, 110, 70)
>>> b.width, b.height, b.center
(100, 50, (60.0, 45.0))
>>> Box.from_norm((0.25, 0.5, 0.5, 0.25), 1920, 1080)
Box(x0=480.0, y0=540.0, x1=1440.0, y1=810.0)
>>> p = Path.line((0, 0), (100, 0))
>>> p.length, p.point(50), p.angle(50)
(100.0, (50.0, 0.0), 0.0)
Functions
|
Place a block of |
|
The centred box holding |
Classes
|
A pixel-space rectangle |
|
A polyline with an arc-length parameterisation. |
- class tituli.geometry.Box(x0, y0, x1, y1)[source]¶
Bases:
objectA pixel-space rectangle
(x0, y0, x1, y1); edges are floats.- classmethod from_norm(nb, width, height)[source]¶
Scale a normalised
(x, y, w, h)into a frame of that size.- Return type:
- class tituli.geometry.Path(points)[source]¶
Bases:
objectA polyline with an arc-length parameterisation.
Build one with the constructors (
line(),arc(),wave(),bezier(),polyline(),from_svg(),from_function()) and query it by distance along the curve:point(s)andangle(s)(degrees, clockwise-positive on screen because y points down).- classmethod arc(center, radius, start_deg, end_deg, *, samples=512)[source]¶
Circular arc; angles in degrees, 0 = right, 90 = down (screen coords).
- Return type:
- classmethod bezier(*controls, samples=512)[source]¶
A Bézier curve of any degree through
controls(De Casteljau).- Return type:
- classmethod circle(center, radius, *, start_deg=-90.0)[source]¶
A full circle starting at the top by default, running clockwise.
- Return type:
- property closed: bool¶
Whether the path ends where it starts (a circle, a closed SVG path).
>>> Path.circle((0, 0), 10).closed, Path.line((0, 0), (1, 1)).closed (True, False)
- fit(box, *, keep_aspect=True)[source]¶
Scale and translate so the path’s bounding box fills
box.Degenerate axes (a horizontal line has zero height) are centred rather than scaled.
- Return type: