Tiling System¶
Overview¶
The tiling system generates regular grids of congruent polygons that cover a geographic bounding box. Its primary role is to provide tile positions for the grid-based layout algorithm: each tile becomes a candidate slot for one symbol. Tiles are generated by a Tiling subclass, and the result is a TilingResult containing tile geometries, per-tile transforms, and adjacency information.
Source: tiling.py
Tiling Types¶
Five concrete tiling classes are provided, covering all regular and semi-regular polygon tilings used in cartography:
| Class | Description |
|---|---|
SquareTiling |
Regular axis-aligned squares |
HexagonTiling |
Regular hexagons; pointy_top parameter selects orientation |
TriangleTiling |
Any triangle; convenience constructors for equilateral, right isosceles, isosceles |
QuadrilateralTiling |
Any quadrilateral; convenience constructors for parallelogram, rectangle, rhombus, trapezoid |
IsohedralTiling |
81 Grünbaum–Shephard isohedral types with numeric parameters and customizable edge curves |
All classes share the same generate(bounds, n_tiles=None, tile_size=None, margin=0.1) interface. Either the number of tiles or the tile size must be specified.
TilingResult¶
generate() returns a TilingResult dataclass:
| Field | Type | Description |
|---|---|---|
polygons |
list of Polygon |
Tile geometries in world coordinates |
transforms |
list of TileTransform |
Per-tile center, rotation (degrees), flipped flag |
adjacency |
NDArray |
Binary edge-adjacency matrix |
vertex_adjacency |
NDArray |
Binary vertex-only adjacency matrix |
tile_size |
float | Tile size parameter used for generation |
inscribed_radius |
float | Radius of the largest inscribed circle |
canonical_tile |
Polygon |
Unit tile shape before applying transforms |
inscribed_radius is used by the layout algorithm to convert area-equivalent symbol radii to tile-space coordinates.
Isohedral Tilings¶
Mathematical Definition¶
A tiling is isohedral (IH) if every tile is congruent and the symmetry group of the tiling acts transitively on its tiles: for any two tiles \(T\) and \(T'\), there exists a symmetry transformation of the entire tiling that maps \(T\) to \(T'\). All 81 isohedral types in the plane are classified in Grünbaum and Shephard's Tilings and Patterns (1987).
IsohedralTiling wraps the tactile C++ library (Python bindings) for isohedral tiling generation. Each type is identified by its IH number (1–93, with gaps) and zero or more real-valued shape parameters.
Edge Shape Types¶
Each tile edge in an isohedral tiling is assigned a shape constraint by the tiling's symmetry group:
| Type | Symbol | Constraint |
|---|---|---|
| Straight | I | Edge is a straight line segment; not customizable |
| Free | J | Edge curve is fully customizable |
| Rotationally symmetric | S | The curve at parameter \(t\) equals the curve at \(1-t\) rotated 180° about the edge midpoint |
| Mirror symmetric | U | The curve is symmetric about the perpendicular bisector of the edge |
When an edge curve is provided, it is defined in canonical edge space as a polyline from \((0, 0)\) to \((1, 0)\), where perpendicular displacement encodes the curve shape. The tiling system enforces the symmetry constraints automatically.
Querying and Creating¶
from carto_flow.symbol_cartogram.tiling import IsohedralTiling
# All triangle-based types with customizable edges
types = IsohedralTiling.find_types(num_vertices=3, has_customizable_edges=True)
# Type metadata
info = IsohedralTiling.type_info(10)
# → {'num_parameters': 0, 'num_vertices': 6, 'edge_shapes': ['J','J','J'], ...}
# Create from type number with optional shape parameters
tiling = IsohedralTiling(tiling_type=68, parameters=[0.25])
# Load a preset configuration (parameters + edge curves)
tiling = IsohedralTiling.from_preset("scalloped_hexagon")
Edge Curves¶
# Assign custom edge curves (polyline in canonical edge space)
tiling = IsohedralTiling(
tiling_type=41,
edge_curves={
0: [(0, 0), (0.25, 0.12), (0.5, 0), (0.75, -0.12), (1, 0)],
1: [(0, 0), (0.25, -0.12), (0.5, 0), (0.75, 0.12), (1, 0)],
}
)
Only edges of type J, S, or U accept curve overrides. S- and U-edges automatically enforce their respective symmetry constraint on the provided curve.
Symbol–Tile Correspondence¶
Each Tiling subclass has a canonical_symbol() method that returns the Symbol instance matching the tile shape. This ensures symbols fit tiles correctly without explicit alignment:
| Tiling | Canonical symbol |
|---|---|
SquareTiling |
SquareSymbol |
HexagonTiling |
HexagonSymbol(pointy_top=...) |
IsohedralTiling |
IsohedralTileSymbol(...) |
tiling.tile_size_for_symbol_size(symbol_size, spacing) computes the tile size required to contain a symbol of a given area-equivalent radius, accounting for the desired spacing gap.
Tilings can be saved to JSON with tiling.save("path.json") and reloaded with IsohedralTiling.load("path.json").
Integration with Grid Layout¶
When GridBasedLayout runs, it calls tiling.generate(bounds, n_tiles=...) to produce enough tiles to cover the input regions, then passes the TilingResult to assign_to_grid_hungarian(). Tile adjacency from TilingResult.adjacency is used directly in the BFS hop-distance computation of the neighbor cost term. See Grid Layout Algorithm for details.