geomotif.bases.tiling
¶
Bases for tilings: one cell repeated on a lattice, or tiles that subdivide.
The two cover the field between them. :class:LatticeTiling is the periodic
case -- square, triangular, hexagonal, rhombille, Cairo, herringbone, Truchet
-- where a single cell is stamped along two basis vectors. :class:Substitution
Tiling is the aperiodic case -- Penrose, Ammann-Beenker, girih -- where a
handful of seed tiles are replaced by smaller copies of themselves, over and
over.
Classes:
| Name | Description |
|---|---|
LatticeTiling |
Base for a periodic tiling: one cell, repeated on two basis vectors. |
SubstitutionTiling |
Base for an aperiodic tiling: seed tiles, subdivided :attr: |
LatticeTiling
dataclass
¶
LatticeTiling(*, region: Bounds, clip: bool = True)
Bases: Motif, ABC
Base for a periodic tiling: one cell, repeated on two basis vectors.
Implement :meth:cell (the geometry of one tile) and :meth:basis (the
two translations that repeat it), and give the motif a :attr:region to
fill::
@register("tiling.square", family="tiling")
@dataclass(frozen=True, slots=True)
class SquareTiling(LatticeTiling):
size: float = 10.0
def basis(self) -> tuple[Point, Point]:
return ((self.size, 0.0), (0.0, self.size))
def cell(self) -> Design:
s = self.size
return Design((Path(((0, 0), (s, 0), (s, s), (0, s)), closed=True),))
:meth:basis is a method rather than a field because for most tilings the
vectors follow from the motif's own parameters, as above; a tiling that
genuinely wants caller-supplied vectors can declare a field and return it.
Methods:
| Name | Description |
|---|---|
basis |
Return the two translation vectors that generate the lattice. |
cell |
Return the geometry of a single cell, at lattice origin. |
basis
abstractmethod
¶
SubstitutionTiling
dataclass
¶
Bases: Motif, ABC
Base for an aperiodic tiling: seed tiles, subdivided :attr:depth times.
The tile type is yours -- a dataclass of three vertices, a rhomb with an orientation, whatever the substitution rule needs. The base only ever passes tiles back to your own methods, so it never has to know.
Implement :meth:seed (the starting tiles), :meth:subdivide (one tile
to its replacements) and :meth:outline (a tile to the strokes that draw
it).
Notes
Tile count grows geometrically -- a rule with three replacements reaches a hundred thousand tiles by depth eleven -- so the expansion is capped and raises rather than exhausting memory.
Shared edges are drawn once per tile that owns them, so a plotter will trace most edges twice. Deduplicating them means comparing floating-point vertices for equality, which is a judgement call about tolerance the base should not be making for you.
Methods:
| Name | Description |
|---|---|
seed |
Return the tiles the subdivision starts from. |
subdivide |
Return the tiles that replace |
outline |
Return the strokes that draw |
tiles |
Return the seed tiles subdivided :attr: |
seed
abstractmethod
¶
subdivide
abstractmethod
¶
tiles
¶
Return the seed tiles subdivided :attr:depth times.
Exposed separately from :meth:build because the tiles themselves are
often what you want -- to count them, to check a substitution rule
preserves area, or to color them by type.