geomotif.core.types
¶
The geometric value types every motif produces and every tool consumes.
A :class:Design is the universal currency of this library: zero or more
stroked :class:Path polylines plus zero or more loose :class:Point s that
carry no stroke (dot art, scatter fields, lattice sites). Motifs build them,
transforms rewrite them, exporters write them out.
Everything here is immutable, so designs compose without aliasing surprises
and can be shared freely between threads. Operations that would mutate return
a new value instead -- :meth:Design.transformed, :meth:Design.resampled,
:meth:Design.fit.
Classes:
| Name | Description |
|---|---|
Bounds |
An axis-aligned rectangle enclosing some geometry. |
Path |
One continuous polyline. |
Design |
The universal result: zero or more strokes plus zero or more loose points. |
Functions:
| Name | Description |
|---|---|
select_styles |
Return |
Bounds
dataclass
¶
An axis-aligned rectangle enclosing some geometry.
Methods:
| Name | Description |
|---|---|
from_points |
Return the tightest bounds containing every point. |
union |
Return the smallest bounds containing both rectangles. |
padded |
Return these bounds grown by |
Attributes:
| Name | Type | Description |
|---|---|---|
width |
float
|
Horizontal extent. |
height |
float
|
Vertical extent. |
center |
Point
|
Midpoint of the rectangle. |
from_points
classmethod
¶
from_points(points: Iterable[Point]) -> Bounds
Return the tightest bounds containing every point.
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/geomotif/core/types.py
union
¶
Return the smallest bounds containing both rectangles.
Source code in src/geomotif/core/types.py
Path
dataclass
¶
One continuous polyline.
closed means the last point connects back to the first. The closing
segment is implied, never stored, so a closed path's points are never
duplicated at the seam.
Points are normalized to a tuple of finite (float, float) pairs at
construction, so any sequence of pairs may be passed in.
Attributes:
| Name | Type | Description |
|---|---|---|
length |
float
|
Total polyline length, including the closing segment if closed. |
bounds |
Bounds
|
Tightest rectangle containing every vertex. |
length
property
¶
Total polyline length, including the closing segment if closed.
A two-point "closed" path is treated as a single open segment: its closing segment retraces the one it already has, and counting that twice reports a length no plotter would ever draw.
Design
dataclass
¶
Design(paths: tuple[Path, ...] = (), points: tuple[Point, ...] = (), meta: Mapping[str, object] = EMPTY_META)
The universal result: zero or more strokes plus zero or more loose points.
meta carries the motif name and its resolved parameters (including any
resolved random seed), which is what makes a design reproducible,
serializable to a spec file, and self-labelling in the gallery.
Methods:
| Name | Description |
|---|---|
transformed |
Return this design with |
flipped_y |
Return this design mirrored about the x-axis. |
resampled |
Return this design resampled to |
snapped |
Return this design with every point moved onto a grid of |
fit |
Return this design scaled and centered inside a |
Attributes:
| Name | Type | Description |
|---|---|---|
bounds |
Bounds
|
Bounds over every point in every path plus the loose points. |
transformed
¶
Return this design with m applied to every point.
Source code in src/geomotif/core/types.py
flipped_y
¶
flipped_y() -> Design
Return this design mirrored about the x-axis.
The y-up/y-down question is a property of the target coordinate space, not of any motif, which is why it lives here rather than as a flag on every builder.
Source code in src/geomotif/core/types.py
resampled
¶
resampled(count: int | None = None, *, step: float | None = None, spacing: SpacingLike | None = None, distribute: Distribution = 'length') -> Design
Return this design resampled to count points (or a fixed step).
See :func:geomotif.core.sampling.resample for the full contract.
Source code in src/geomotif/core/types.py
snapped
¶
snapped(step: float = 1.0, *, mode: SnapMode = 'half-even', drop_duplicates: bool = True) -> Design
Return this design with every point moved onto a grid of step.
Rounding the geometry rather than each file as it is written, so every exporter agrees and a plot shows what the file will hold. Defaults to whole units.
See :func:geomotif.core.transform.snap for the full contract.
Source code in src/geomotif/core/types.py
fit
¶
fit(width: float, height: float, *, padding: float = 0.0, flip_y: bool = False) -> Design
Return this design scaled and centered inside a width x height canvas.
Scaling is uniform, so the design is never distorted; it is centered
in whichever axis has slack. The result sits in [0, width] x
[0, height], with flip_y=True producing y-down (screen/SVG)
coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
width
|
float
|
Canvas size. Both must be positive. |
required |
height
|
float
|
Canvas size. Both must be positive. |
required |
padding
|
float
|
Margin reserved on all four sides. |
0.0
|
flip_y
|
bool
|
Mirror vertically so y increases downward. |
False
|
Returns:
| Type | Description |
|---|---|
Design
|
The fitted design. A design with no extent in either axis (a single point, or a perfectly vertical line) is translated but never scaled, since there is no finite scale that fills a canvas from nothing. |
Source code in src/geomotif/core/types.py
select_styles
¶
select_styles(meta: Mapping[str, object], *, paths: Sequence[int] | None = None, points: Sequence[int] | None = None) -> Mapping[str, object]
Return meta with its style lists following reshaped geometry.
Any operator that drops, splits or reorders a design's strokes has to say
so, or the metadata it carries over lands on the wrong geometry -- a
clipped design whose colors have all shifted by one. paths and
points give the source index of every element the result keeps, in
the order it keeps them, which is something every such operator knows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
meta
|
mapping
|
The metadata to rewrite. Returned unchanged, and uncopied, when it carries no styles at all -- which is the usual case. |
required |
paths
|
sequence of int
|
Source indices, one per element of the result. |
None
|
points
|
sequence of int
|
Source indices, one per element of the result. |
None
|
Returns:
| Type | Description |
|---|---|
Mapping[str, object]
|
Ready to hand to :class: |