Source: https://gometry.monicz.dev/api/tiles/

# XYZ tiles

Web Mercator XYZ tiles, quadkeys, tile hierarchies, and area covers.

**Related:** [Grid-generic API](https://gometry.monicz.dev/api/grids/)

## Types

## Tile

Accepted call forms

```python
Tile(value: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str, /) -> Tile
```

```python
Tile(value: Point, /, *, zoom: int | integer[Any]) -> Tile
```

```python
Tile(*, lon: FloatScalar | ScalarFloatArray, lat: FloatScalar | ScalarFloatArray, zoom: int | integer[Any]) -> Tile
```

```python
Tile(*, x: int | integer[Any], y: int | integer[Any], zoom: int | integer[Any]) -> Tile
```

One XYZ web-mercator tile: the slippy-map `z/x/y` address.

Wraps the tile with typed accessors (`tile.zoom`/`x`/`y`,
`tile.token`, `tile.polygon`, `tile.center`) and hierarchy
moves (`parent`/`children`/`neighbors`). The token is the Bing
quadkey (empty at `z0`); the 64-bit id packs `(zoom, Morton x/y)`
so sorted ids group spatial neighbors. Convert via `Tile(value)`,
`Tile(Point(...), zoom=...)`, `Tile(lon=..., lat=..., zoom=...)`, or
`Tile(x=..., y=..., zoom=...)`. Coordinate frames are always named.
Geographic point ownership follows the emitted binary64 tile boundaries,
with longitude west-inclusive/east-exclusive and latitude
north-inclusive/south-exclusive ties. This is a representational boundary
contract, not a claim of exact ideal-transcendental Web Mercator rounding.

One XYZ tile from a packed id, quadkey, lon/lat keywords, point geometry,
or explicit `x=`/`y=` tile coordinates.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `Tile \| (int \| integer[Any] \| ndarray[tuple[()], dtype[signedinteger[Any] \| unsignedinteger[Any]]]) \| str \| Point` | A tile id/quadkey, or a point geometry when paired with `zoom`. | `varies by call form` |
| `zoom` | `int \| integer[Any]` | Zoom level (`0`-`29`); keyword-only, required for every coordinate form. | `varies by call form` |
| `lon` | `FloatScalar \| ScalarFloatArray` | Geographic coordinates, supplied together with `zoom`. They are keyword-only because two bare numbers do not select a coordinate frame. | `varies by call form` |
| `lat` | `FloatScalar \| ScalarFloatArray` | Geographic coordinates, supplied together with `zoom`. They are keyword-only because two bare numbers do not select a coordinate frame. | `varies by call form` |
| `x` | `int \| integer[Any]` | Explicit tile column/row (keyword-only, with `zoom`) — never inferred from a positional pair, so lon/lat can't be misread as tile coordinates. | `varies by call form` |
| `y` | `int \| integer[Any]` | Explicit tile column/row (keyword-only, with `zoom`) — never inferred from a positional pair, so lon/lat can't be misread as tile coordinates. | `varies by call form` |

Returns:

| Type | Description |
| --- | --- |
| `Tile` |  |

Raises:

| Type | Description |
| --- | --- |
| `ParseError` | If `value` is not a valid tile id or quadkey. |
| `GeometryError` | If `zoom` is out of range, or `x`/`y` is outside `[0, 2**zoom)`. |
| `InvalidGeometryError` | If a scalar coordinate is non-finite or out of range. |

### morton `property`

```python
morton: int
```

The Morton (Z-order) index of `x`/`y` within this zoom.

Returns:

| Type | Description |
| --- | --- |
| `int` |  |

### x `property`

```python
x: int
```

Tile column (west to east).

Returns:

| Type | Description |
| --- | --- |
| `int` |  |

### y `property`

```python
y: int
```

Tile row (north to south).

Returns:

| Type | Description |
| --- | --- |
| `int` |  |

### zoom `property`

```python
zoom: int
```

Zoom level of this tile (`0`-`29`).

Returns:

| Type | Description |
| --- | --- |
| `int` |  |

### children

```python
children(zoom: int | None = None) -> CellArray[Tile]
```

Child cells at a finer zoom.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `zoom` | `int` | Target zoom; must not be coarser than this cell's. Defaults to one finer than this cell's zoom; a maximum-depth cell has no children and yields an empty CellArray. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `CellArray of Tile` | The descendant cells in the grid's public identity order. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the target depth is invalid for this cell. |

Examples:

```pycon
>>> import gometry as gm
>>> cell = gm.tile_cover(gm.Point(-122.4194, 37.7749, crs=4326), zoom=10)[0]
>>> assert cell is not None
>>> len(cell.children())
4
```

### children\_count

```python
children_count(zoom: int | None = None) -> int
```

Number of descendant cells at a finer zoom, counted closed-form without materializing them.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `zoom` | `int` | Target zoom; must not be coarser than this cell's. Defaults to one finer than this cell's zoom; a maximum-depth cell has no children and returns `0`. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `int` | The exact descendant count. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the target depth is coarser than this cell's, or invalid. |

Examples:

```pycon
>>> import gometry as gm
>>> cell = gm.tile_cover(gm.Point(-122.4194, 37.7749, crs=4326), zoom=10)[0]
>>> assert cell is not None
>>> cell.children_count()
4
```

### parent

```python
parent(zoom: int | None = None) -> Tile
```

Parent cell at a coarser zoom.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `zoom` | `int` | Target zoom; must not be finer than this cell's. Defaults to one coarser than this cell's zoom. | `None` |

Returns:

| Type | Description |
| --- | --- |
| `Tile` | The ancestor cell. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the target depth is invalid for this cell. |

Examples:

```pycon
>>> import gometry as gm
>>> cell = gm.tile_cover(gm.Point(-122.4194, 37.7749, crs=4326), zoom=10)[0]
>>> assert cell is not None
>>> parent = cell.parent()
>>> assert parent is not None
>>> str(parent)
'023010203'
```

## Functions

## tile\_bounding\_cell

```python
tile_bounding_cell(value: Geometry | GeometryArray[Geometry | None] | Iterable[float]) -> Tile
```

Return the deepest single tile containing a geometry or lon/lat bounds.

The mercantile `bounding_tile`: descends the lower-corner tile and accepts
a candidate only after its complete lon/lat rectangle contains the query.
An antimeridian-spanning region is contained by the wrapped z0 world tile;
narrower tiles cannot represent both sides of the seam.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `value` | `Geometry, GeometryArray, or sequence of float` | A geometry/array (non-WGS84 frames reproject), or a bare lon/lat `(minx, miny, maxx, maxy)` bounds. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `Tile` | The deepest tile whose rectangle contains the whole bounds. |

Raises:

| Type | Description |
| --- | --- |
| `InvalidGeometryError` | If the geometry is empty or coordinates leave the lon/lat domain. |
| `GeometryError` | If bare bounds are not ordered min <= max. |

Examples:

```pycon
>>> import gometry as gm
>>> berlin = gm.box(13.3, 52.4, 13.5, 52.6, crs=4326)
>>> tile = gm.tile_bounding_cell(berlin)
>>> (tile.zoom, tile.x, tile.y)
(5, 17, 10)
```

## tile\_cells

Accepted call forms

```python
tile_cells(values: GeometryArray[Point] | Iterable[Point] | (Sequence[Sequence[float]] | ndarray[tuple[int, int], dtype[floating[Any] | signedinteger[Any] | unsignedinteger[Any] | bool_]]) | FloatInput, lat: FloatInput | None = None, *, zoom: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer) -> CellArray[Tile]
```

```python
tile_cells(values: GeometryArray[Point | None] | Iterable[Point | None], lat: None = None, *, zoom: int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]] | ndarray[tuple[int], dtype[signedinteger[Any] | unsignedinteger[Any]]] | Iterable[int] | Buffer) -> CellArray[Tile | None]
```

Build tiles from points, coordinate rows, or parallel lon/lat columns.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `values` | `GeometryArray of Point, iterable of Point or None, coordinate matrix, or float` | Point geometries (`None` makes a missing cell), a coordinate matrix with at least two columns, or WGS84 longitudes. Iterable points must share one CRS and epoch; projected point inputs are reprojected to WGS84. Coordinate matrices use only X and Y, ignoring extra ordinates. | *required* |
| `lat` | `float or sequence of float` | WGS84 latitude per row when `values` supplies longitudes. Coordinate columns broadcast numpy-style; at least one must be a sequence. Latitudes outside the square Web Mercator tile grid (±85.051129°) raise `InvalidGeometryError` (no silent clamp). | `None` |
| `zoom` | `int or sequence of int` | Zoom level (0-29; finer at higher values). A scalar broadcasts to every row; an array supplies one zoom per row. Geographic point ownership follows the emitted binary64 tile edges, with west-inclusive/east-exclusive longitude and north-inclusive/south-exclusive latitude ties. | *required* |

Returns:

| Type | Description |
| --- | --- |
| `CellArray of Tile` | One tile per input coordinate. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the input is scalar, zoom is invalid, or coordinate columns have different lengths. |
| `InvalidGeometryError` | If coordinates are non-finite or leave the lon/lat domain, or a latitude is outside the square Web Mercator tile grid (±85.051129°). |

See Also

[Tile](https://gometry.monicz.dev/api/tiles/#gometry.Tile "Tile") : Build a single tile.

Examples:

```pycon
>>> import gometry as gm
>>> tile = gm.Tile(lon=-105.939, lat=35.687, zoom=9)
>>> (tile.zoom, tile.x, tile.y)
(9, 105, 201)
```

## tile\_cover

Accepted call forms

```python
tile_cover(geom: GeometryArray[Geometry] | Iterable[Geometry], zoom: int, *, cell_rule: Literal['center', 'within', 'overlap', 'bbox'] = 'overlap', max_cells: int | None = 1000000) -> Groups[CellArray[Tile]]
```

```python
tile_cover(geom: GeometryArray[Geometry | None] | Iterable[Geometry | None], zoom: int, *, cell_rule: Literal['center', 'within', 'overlap', 'bbox'] = 'overlap', max_cells: int | None = 1000000) -> Groups[CellArray[Tile] | None]
```

```python
tile_cover(geom: Geometry, zoom: int, *, cell_rule: Literal['center', 'within', 'overlap', 'bbox'] = 'overlap', max_cells: int | None = 1000000) -> CellArray[Tile]
```

Cover a geometry with Web Mercator tiles at a fixed zoom.

The result is a `CellArray` for scalar input or `Groups[CellArray]` for
array input, with tiles selected by `cell_rule`. Keep the source geometry
separately and use the free `gm.*` predicates for exact geometry
questions.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `geom` | `Geometry, GeometryArray, or iterable of Geometry or None` | Geometry to cover (WGS84 lon/lat or projected). A scalar returns a flat cell array; an array or iterable returns one group per input row. `None` produces a missing group; a present empty geometry produces an empty group. | *required* |
| `zoom` | `int` | Tile zoom (`0`-`29`; finer at higher values). Tile rectangles use their emitted binary64 boundaries; this is a representational contract rather than exact ideal-transcendental Web Mercator arithmetic. | *required* |
| `cell_rule` | `('within', 'center', 'overlap', 'bbox')` | Which cells to materialize. `'within'` selects cells entirely inside; `'center'` selects cells whose center is inside; `'overlap'` selects every cell touching the geometry; and `'bbox'` selects every cell meeting the geometry's envelope (one window per part, split at the antimeridian). The rule never affects exact predicates. | `'within'` |
| `max_cells` | `int or None` | Hard cap on returned cells and retained result allocation. Discarded candidates do not consume it; array calls apply it cumulatively across groups. Pass `None` for unlimited output (bounded only by memory). | `1000000` |

Returns:

| Type | Description |
| --- | --- |
| `CellArray or Groups[CellArray]` | A scalar returns a `CellArray`; an array returns one `CellArray` group per input geometry. |

Raises:

| Type | Description |
| --- | --- |
| `GeometryError` | If the geometry, zoom, `cell_rule`, or `max_cells` is invalid, or if the returned coverage would exceed `max_cells`. |
| `InvalidGeometryError` | If the geometry is empty or any non-polar latitude is outside the square Web Mercator tile grid (±85.05112878 degrees). |

Examples:

```pycon
>>> import gometry as gm
>>> point = gm.Point(1, 1)
>>> cells = gm.tile_cover(point, zoom=0)
>>> len(cells)
1
```

## tile\_difference

```python
tile_difference(left: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None], right: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None]) -> CellArray[Tile]
```

Hierarchy-aware difference of two tile cell sets.

Cells of `left` partially covered by `right` split into children
until the remainder is exact; the result is normalized in the grid's
public identity order.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Tile, int, str, or iterable of those with missing values skipped` | The two cell sets (any mix of cell objects, ids, or tokens). | *required* |
| `right` | `Tile, int, str, or iterable of those with missing values skipped` | The two cell sets (any mix of cell objects, ids, or tokens). | *required* |

Returns:

| Type | Description |
| --- | --- |
| `CellArray of Tile` |  |

Raises:

| Type | Description |
| --- | --- |
| `ParseError` | If an id or token is not a valid tile cell. |

Examples:

```pycon
>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cells = [cell for cell in gm.tile_cover(p, zoom=10) if cell is not None]
>>> len(gm.tile_difference(cells, []))
1
```

## tile\_intersection

```python
tile_intersection(left: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None], right: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None]) -> CellArray[Tile]
```

Hierarchy-aware intersection of two tile cell sets.

A cell survives where the two sets overlap; ancestor/descendant overlap
keeps the finer cell.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Tile, int, str, or iterable of those with missing values skipped` | The two cell sets (any mix of cell objects, ids, or tokens). | *required* |
| `right` | `Tile, int, str, or iterable of those with missing values skipped` | The two cell sets (any mix of cell objects, ids, or tokens). | *required* |

Returns:

| Type | Description |
| --- | --- |
| `CellArray of Tile` |  |

Raises:

| Type | Description |
| --- | --- |
| `ParseError` | If an id or token is not a valid tile cell. |

Examples:

```pycon
>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cells = [cell for cell in gm.tile_cover(p, zoom=10) if cell is not None]
>>> len(gm.tile_intersection(cells, cells))
1
```

## tile\_union

```python
tile_union(left: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None], right: Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | Iterable[Tile | (int | integer[Any] | ndarray[tuple[()], dtype[signedinteger[Any] | unsignedinteger[Any]]]) | str | None]) -> CellArray[Tile]
```

Hierarchy-aware union of two tile cell sets.

Returns the normalized cell union in the grid's public identity
order: contained cells are absorbed by their ancestors and complete
sibling groups are merged into parents.

Parameters:

| Name | Type | Description | Default |
| --- | --- | --- | --- |
| `left` | `Tile, int, str, or iterable of those with missing values skipped` | A single cell identity or a collection on either side (any accepted mix of cell objects and identity values for this grid). | *required* |
| `right` | `Tile, int, str, or iterable of those with missing values skipped` | A single cell identity or a collection on either side (any accepted mix of cell objects and identity values for this grid). | *required* |

Returns:

| Type | Description |
| --- | --- |
| `CellArray of Tile` |  |

Raises:

| Type | Description |
| --- | --- |
| `ParseError` | If an id or token is not a valid tile cell. |

Examples:

```pycon
>>> import gometry as gm
>>> p = gm.Point(-122.4194, 37.7749, crs=4326)
>>> cells = [cell for cell in gm.tile_cover(p, zoom=10) if cell is not None]
>>> len(gm.tile_union(cells, cells))
1
```
