= Grid Graph

A multi-dimensional, rectangular grid of vertices with user-defined dimension
lengths and optional wrapping per dimension.

*Defined in:* `<boost/graph/grid_graph.hpp>` +
*Models:* IncidenceGraph, AdjacencyGraph, VertexListGraph, EdgeListGraph,
BidirectionalGraph, AdjacencyMatrix

NOTE: `grid_graph` does not support bundled properties. To associate data with
grid cells (e.g. terrain costs), maintain an external container indexed by the
grid's vertex index: `std::vector<double> cost(num_vertices(g));`

== Flat grid

The simplest case: a rectangular grid with no wrapping. Corner vertices have
fewer neighbors than interior vertices.

image::figs/grid_graph_unwrapped.png[3x3 unwrapped grid]

[source,cpp]
----
include::example$adaptors/grid_graph_unwrapped.cpp[]
----

[,text]
----
include::example$adaptors/grid_graph_unwrapped.txt[]
----

== Torus (all dimensions wrap)

Pass `true` as the second constructor argument to wrap all dimensions. Every
vertex now has the same degree.

image::figs/grid_graph_wrapped.png[3x3 wrapped grid (torus)]

[source,cpp]
----
include::example$adaptors/grid_graph_torus.cpp[]
----

[,text]
----
include::example$adaptors/grid_graph_torus.txt[]
----

== Cylinder (mixed wrapping)

Pass a `boost::array<bool, Dimensions>` to control wrapping per dimension.
Here dimension 0 wraps (cylinder) but dimension 1 does not.

[source,cpp]
----
include::example$adaptors/grid_graph_cylinder.cpp[]
----

[,text]
----
include::example$adaptors/grid_graph_cylinder.txt[]
----

== Higher dimensions

The `Dimensions` template parameter is a compile-time constant. A 3D grid
works the same way.

[source,cpp]
----
include::example$adaptors/grid_graph_3d.cpp[]
----

[,text]
----
include::example$adaptors/grid_graph_3d.txt[]
----

== Synopsis

[source,cpp]
----
template <std::size_t Dimensions,
          typename VertexIndex = std::size_t,
          typename EdgeIndex = VertexIndex>
class grid_graph;
----

== Template Parameters

[cols="1,3,1",options="header"]
|===
| Parameter | Description | Default

| `Dimensions`
| Number of dimensions (compile-time constant).
|

| `VertexIndex`
| Integer type for vertex indices.
| `std::size_t`

| `EdgeIndex`
| Integer type for edge indices.
| same as `VertexIndex`
|===

== Constructors

[source,cpp]
----
grid_graph(boost::array<VertexIndex, Dimensions> lengths);
----

Create an unwrapped grid with the given dimension lengths.

'''

[source,cpp]
----
grid_graph(boost::array<VertexIndex, Dimensions> lengths,
           bool wrap_all);
----

Create a grid where all dimensions wrap (`true`) or none wrap (`false`).

'''

[source,cpp]
----
grid_graph(boost::array<VertexIndex, Dimensions> lengths,
           boost::array<bool, Dimensions> wrap_per_dim);
----

Create a grid with per-dimension wrapping control.

== Member Functions

[source,cpp]
----
std::size_t dimensions();
----

Returns the number of dimensions.

'''

[source,cpp]
----
VertexIndex length(std::size_t dim);
----

Returns the length of dimension `dim`.

'''

[source,cpp]
----
bool wrapped(std::size_t dim);
----

Returns whether dimension `dim` wraps.

'''

[source,cpp]
----
vertex_descriptor next(vertex_descriptor v, std::size_t dim,
                       vertices_size_type distance = 1);
vertex_descriptor previous(vertex_descriptor v, std::size_t dim,
                           vertices_size_type distance = 1);
----

Move along a dimension. In an unwrapped dimension, `next` stops at the last
vertex and `previous` stops at the first. In a wrapped dimension, movement
wraps around.

== Indexing

Vertices and edges can be addressed by integer index:

[source,cpp]
----
vertex_descriptor vertex(vertices_size_type idx, const grid_graph& g);
edges_size_type   get(edge_index_t, const grid_graph& g, edge_descriptor e);
edge_descriptor   edge_at(edges_size_type idx, const grid_graph& g);
----

The vertex descriptor is a `boost::array<VertexIndex, Dimensions>` that can
be indexed by dimension: `v[0]` is the position in dimension 0, `v[1]` in
dimension 1, etc.
