Skip to content

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.