-- |
-- Module      :  Math.Geometry.Grid
-- Copyright   :  (c) Amy de Buitléir 2012-2015
-- License     :  BSD-style
-- Maintainer  :  amy@nualeargais.ie
-- Stability   :  experimental
-- Portability :  portable
-- A regular arrangement of tiles. Grids have a variety of uses,
-- including games and self-organising maps.
-- The userguide is available at 
-- <https://github.com/mhwombat/grid/wiki>.
-- In this package, tiles are called \"triangular\", \"square\", etc.,
-- based on the number of /neighbours/ they have.
-- For example, a square tile has four neighbours, and a hexagonal
-- tile has six.
-- There are only three regular polygons that can tile a plane:
-- triangles, squares, and hexagons.
-- Of course, other plane tilings are possible if you use irregular 
-- polygons, or curved shapes, or if you combine tiles of different 
-- shapes.
-- When you tile other surfaces, things get very interesting.
-- Octagons will tile a /hyperbolic/ plane.
-- (Alternatively, you can think of these as squares on a board game
-- where diagonal moves are allowed.)
-- For a board game, you probably want to choose the grid type based
-- on the number of /directions/ a player can move, rather than the
-- number of sides the tile will have when you display it.
-- For example, for a game that uses square tiles and allows the user
-- to move diagonally as well as horizontally and vertically,
-- consider using one of the grids with /octagonal/ tiles to model the
-- board.
-- You can still /display/ the tiles as squares, but for internal
-- calculations they are octagons.
-- NOTE: Version 6.0 moved the various grid flavours to sub-modules.
-- NOTE: Version 4.0 uses associated (type) synonyms instead of 
-- multi-parameter type classes.
-- NOTE: Version 3.0 changed the order of parameters for many functions.
-- This makes it easier for the user to write mapping and folding
-- operations.
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, 
  FlexibleInstances #-}

module Math.Geometry.Grid
    -- * Example
    -- $Example

    -- * Grids
    Grid(indices, distance, minDistance, neighbours, neighbour, 
      contains, tileCount, null, nonNull, edges, viewpoint, 
      isAdjacent, adjacentTilesToward, minimalPaths, directionTo),

    -- * Finite grids

    -- * Bounded grids
  ) where

import Math.Geometry.GridInternal (Grid(..), FiniteGrid(..), 

{- $Example
   Create a grid.

>ghci> let g = hexHexGrid 3
>ghci> indices g

   Find out if the specified index is contained within the grid.

>ghci> g `contains` (0,-2)
>ghci> g `contains` (99,99)

   Find out the minimum number of moves to go from one tile in a grid to
   another tile, moving between adjacent tiles at each step.

>ghci> distance g (0,-2) (0,2)

   Find out the minimum number of moves to go from one tile in a grid to
   any other tile, moving between adjacent tiles at each step.

>ghci> viewpoint g (1,-2)

   Find out which tiles are adjacent to a particular tile.

>ghci> neighbours g (-1,1)

   Find how many tiles are adjacent to a particular tile.
   (Note that the result is consistent with the result from the previous

>ghci> numNeighbours g (-1,1)

   Find out if an index is valid for the grid.

>ghci> g `contains` (0,0)
>ghci> g `contains` (0,12)

   Find out the physical dimensions of the grid.

>ghci> size g

   Get the list of boundary tiles for a grid.

>ghci> boundary g

   Find out the number of tiles in the grid.

>ghci> tileCount g

   Check if a grid is null (contains no tiles).

>ghci> null g
>ghci> nonNull g

   Find the central tile(s) (the tile(s) furthest from the boundary).

>ghci> centre g

   Find all of the minimal paths between two points.

>ghci> let g = hexHexGrid 3
>ghci> minimalPaths g (0,0) (2,-1)

   Find all of the pairs of tiles that are adjacent.

>ghci> edges g

   Find out if two tiles are adjacent.

>ghci> isAdjacent g (-2,0) (-2,1)
>ghci> isAdjacent g (-2,0) (0,1)