# `StaticMaps.TileGrid`
[🔗](https://gitlab.com/tristanperalta/staticmaps/blob/v0.1.0/lib/static_maps/tile_grid.ex#L1)

Works out which tiles cover a viewport and where each one is drawn.

A source's tiles are either 256 or 512 pixels. A 512-pixel tile at zoom `z - 1` covers
the same ground as four 256-pixel tiles at zoom `z`, so for a 512-pixel source the grid
asks for tiles one zoom lower than the viewport's.

Three rules keep the grid correct at the edges of the world:

  * placements are computed from the unwrapped column, and only the tile key wraps, so
    a view across the antimeridian puts each tile on the correct side;
  * rows above the north edge or below the south edge are left out rather than wrapped,
    so the area past the poles stays empty;
  * a tile needed in several places, as happens when a wide image at zoom 0 shows the
    world more than once, appears once per place but has one key, and `keys/1` lists
    each key once.

# `key`

```elixir
@type key() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}
```

# `placement`

```elixir
@type placement() :: %{key: key(), at: {integer(), integer()}}
```

# `t`

```elixir
@type t() :: %StaticMaps.TileGrid{
  tile_px: pos_integer(),
  tiles: [placement()],
  zoom: non_neg_integer()
}
```

* `:zoom` — the zoom of the tiles to fetch
* `:tile_px` — the width and height each tile is drawn at, in output pixels
* `:tiles` — every placement, row by row from the top left

# `build`

```elixir
@spec build(StaticMaps.Viewport.t(), 256 | 512) :: t()
```

Builds the grid for `viewport` from a source whose tiles are `tile_size` pixels.

Raises `ArgumentError` for a 512-pixel source at viewport zoom 0, which has no tiles
large enough to cover it.

    iex> vp = StaticMaps.Viewport.new({0, 0}, 0, {256, 256}, 1)
    iex> StaticMaps.TileGrid.build(vp, 256).tiles
    [%{key: {0, 0, 0}, at: {0, 0}}]

# `keys`

```elixir
@spec keys(t()) :: [key()]
```

The distinct tile keys in `grid`, in the order they first appear.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
