packages feed

grid-7.8.6: test/Math/Geometry/Grid/TriangularQC.hs

------------------------------------------------------------------------
-- |
-- Module      :  Math.Geometry.Grid.TriangularQC
-- Copyright   :  (c) Amy de Buitléir 2012-2016
-- License     :  BSD-style
-- Maintainer  :  amy@nualeargais.ie
-- Stability   :  experimental
-- Portability :  portable
--
-- QuickCheck tests.
--
------------------------------------------------------------------------
{-# LANGUAGE FlexibleContexts, ExistentialQuantification, 
    TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Math.Geometry.Grid.TriangularQC
  (
    test
  ) where

import Math.Geometry.Grid.TriangularInternal
import Math.Geometry.GridInternal
import Math.Geometry.GridQC

import Prelude hiding (null)
import Test.Framework (Test, testGroup)
import Test.QuickCheck
  (Gen, Arbitrary, arbitrary, sized, choose, elements, Property,
    vectorOf, suchThat)

instance Arbitrary TriDirection where
  arbitrary =
    elements [South, Northwest, Northeast, North, Southeast, Southwest]

--
-- Unbounded grids with triangular tiles
--

data UnboundedTriGridTD =
  UnboundedTriGridTD [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData UnboundedTriGridTD where
  type BaseGrid UnboundedTriGridTD = UnboundedTriGrid
  grid _ = UnboundedTriGrid
  points (UnboundedTriGridTD ps _ _) = ps
  twoClosePoints (UnboundedTriGridTD _ qs _) = qs
  neighbourCountBounds _ = (3, 3)
  direction (UnboundedTriGridTD _ _ d) = d


valid :: (Int,Int) -> Bool
valid (x,y) = even (x+y)

bothValid :: ((Int,Int),(Int,Int)) -> Bool
bothValid (a,b) = valid a && valid b

sizedUnboundedTriGridTD :: Int -> Gen UnboundedTriGridTD
sizedUnboundedTriGridTD n = do
  k <- choose (0,n)
  ps <- vectorOf (k+2) (arbitrary `suchThat` valid) :: Gen [(Int,Int)]
  qs <- chooseClosePointsUnbounded `suchThat` bothValid
  d <- arbitrary
  return $ UnboundedTriGridTD ps qs d

instance Arbitrary UnboundedTriGridTD where
  arbitrary = sized sizedUnboundedTriGridTD

unboundedTriGridProperties :: [(String, UnboundedTriGridTD -> Property)]
unboundedTriGridProperties = gridProperties "UnboundedTriGrid"

unboundedTriGridTests :: [Test]
unboundedTriGridTests = makeTests unboundedTriGridProperties


--
-- Triangular grids with triangular tiles
--

data TriTriGridTD =
  TriTriGridTD TriTriGrid [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData TriTriGridTD where
  type BaseGrid TriTriGridTD = TriTriGrid
  grid (TriTriGridTD g _ _ _) = g
  points (TriTriGridTD _ ps _ _) = ps
  twoClosePoints (TriTriGridTD _ _ qs _) = qs
  neighbourCountBounds _ = (0, 3)
  direction (TriTriGridTD _ _ _ d) = d

instance TestDataF TriTriGridTD where
  maxDistance (TriTriGridTD g _ _ _) = 2*(s-1)
    where s = size g
  expectedTileCount (TriTriGridTD g _ _ _) = s*s
    where s = size g

instance TestDataB TriTriGridTD where
  expectedBoundaryCount (TriTriGridTD g _ _ _) = (f . size) g
    where f 0 = 0
          f 1 = 1
          f s = 3*(s-1)

-- We want the number of tiles in a test grid to be O(n)
sizedTriTriGridTD :: Int -> Gen TriTriGridTD
sizedTriTriGridTD n = do
  let g = triTriGrid (2 * isqrt n)
  ps <- chooseIndices g n
  qs <- chooseClosePoints g `suchThat` bothValid
  d <- arbitrary
  return $ TriTriGridTD g ps qs d

instance Arbitrary TriTriGridTD where
  arbitrary = sized sizedTriTriGridTD

triTriGridProperties :: [(String, TriTriGridTD -> Property)]
triTriGridProperties = gridProperties "TriTriGrid"
  ++ finiteGridProperties "TriTriGrid"
  ++ boundedGridProperties "TriTriGrid"

triTriGridTests :: [Test]
triTriGridTests = makeTests triTriGridProperties

--
-- Parallelogram-shaped grids with triangular tiles
--

data ParaTriGridTD =
  ParaTriGridTD ParaTriGrid [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData ParaTriGridTD where
  type BaseGrid ParaTriGridTD = ParaTriGrid
  grid (ParaTriGridTD g _ _ _) = g
  points (ParaTriGridTD _ ps _ _) = ps
  twoClosePoints (ParaTriGridTD _ _ qs _) = qs
  neighbourCountBounds _ = (0, 3)
  direction (ParaTriGridTD _ _ _ d) = d

instance TestDataF ParaTriGridTD where
  maxDistance (ParaTriGridTD g _ _ _) = 2*(r+c) - 3
    where (r, c) = size g
  expectedTileCount (ParaTriGridTD g _ _ _) = 2*r*c
    where (r, c) = size g

instance TestDataB ParaTriGridTD where
  expectedBoundaryCount (ParaTriGridTD g _ _ _) = (f . size) g
    where f (0,_) = 0
          f (_,0) = 0
          f (1,c) = 2*c
          f (r,1) = 2*r
          f (r,c) = 2*(r+c-1)

-- We want the number of tiles in a test grid to be O(n)
sizedParaTriGridTD :: Int -> Gen ParaTriGridTD
sizedParaTriGridTD n = do
  r <- choose (0,n)
  let c = n `div` (2*r + 1)
  let g = paraTriGrid r c
  ps <- chooseIndices g n
  qs <- chooseClosePoints g `suchThat` bothValid
  d <- arbitrary
  return $ ParaTriGridTD g ps qs d

instance Arbitrary ParaTriGridTD where
  arbitrary = sized sizedParaTriGridTD

paraTriGridProperties :: [(String, ParaTriGridTD -> Property)]
paraTriGridProperties = gridProperties "ParaTriGrid"
  ++ finiteGridProperties "ParaTriGrid"
  ++ boundedGridProperties "ParaTriGrid"

paraTriGridTests :: [Test]
paraTriGridTests = makeTests paraTriGridProperties


--
-- Rectangular grids with triangular tiles
--

data RectTriGridTD =
  RectTriGridTD RectTriGrid [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData RectTriGridTD where
  type BaseGrid RectTriGridTD = RectTriGrid
  grid (RectTriGridTD g _ _ _) = g
  points (RectTriGridTD _ ps _ _) = ps
  twoClosePoints (RectTriGridTD _ _ qs _) = qs
  neighbourCountBounds _ = (0, 3)
  direction (RectTriGridTD _ _ _ d) = d

instance TestDataF RectTriGridTD where
  maxDistance (RectTriGridTD g _ _ _) = 2*(r+c) - 3
    where (r, c) = size g
  expectedTileCount (RectTriGridTD g _ _ _) = 2*r*c
    where (r, c) = size g

instance TestDataB RectTriGridTD where
  expectedBoundaryCount (RectTriGridTD g _ _ _) = (f . size) g
    where f (0,_) = 0
          f (_,0) = 0
          f (1,c) = 2*c
          f (r,1) = 2*r
          f (r,c) = 2*(r+c-1)

-- We want the number of tiles in a test grid to be O(n)
sizedRectTriGridTD :: Int -> Gen RectTriGridTD
sizedRectTriGridTD n = do
  r <- choose (0,n)
  let c = n `div` (2*r + 1)
  let g = rectTriGrid r c
  ps <- chooseIndices g n
  qs <- chooseClosePoints g `suchThat`
    (\(a,b) -> bothValid (a,b) && inRectBounds r c a && inRectBounds r c b)
  d <- arbitrary
  return $ RectTriGridTD g ps qs d

inRectBounds :: Int -> Int -> (Int, Int) -> Bool
inRectBounds _ c (x, y) = xMin <= x && x <= xMax
  where xMin = if even y then w else w+1
        w = -2*((y+1) `div` 4)
        xMax = xMin + 2*(c-1)

instance Arbitrary RectTriGridTD where
  arbitrary = sized sizedRectTriGridTD

rectTriGridProperties :: [(String, RectTriGridTD -> Property)]
rectTriGridProperties = gridProperties "RectTriGrid"
  ++ finiteGridProperties "RectTriGrid"
  ++ boundedGridProperties "RectTriGrid"

rectTriGridTests :: [Test]
rectTriGridTests = makeTests rectTriGridProperties


--
-- Toroidal grids with triangular tiles
--

data TorTriGridTD =
  TorTriGridTD TorTriGrid [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData TorTriGridTD where
  type BaseGrid TorTriGridTD = TorTriGrid
  grid (TorTriGridTD g _ _ _) = g
  points (TorTriGridTD _ ps _ _) = ps
  twoClosePoints (TorTriGridTD _ _ qs _) = qs
  neighbourCountBounds _ = (0, 3)
  direction (TorTriGridTD _ _ _ d) = d

instance TestDataF TorTriGridTD where
  maxDistance (TorTriGridTD g _ _ _) = 2*(r+c) - 3
    where (r, c) = size g
  expectedTileCount (TorTriGridTD g _ _ _) = 2*r*c
    where (r, c) = size g

-- We want the number of tiles in a test grid to be O(n)
sizedTorTriGridTD :: Int -> Gen TorTriGridTD
sizedTorTriGridTD n = do
  r0 <- choose (0,n `div` 2)
  let r = 2*r0
  let c = n `div` (2*r + 1)
  let g = torTriGrid r c
--  r <- choose (0,n)
--  let c = n `div` (2*r + 1)
--  let g = torTriGrid r c
  ps <- chooseIndices g n
  qs <- chooseClosePoints g `suchThat` bothValid
  d <- arbitrary
  return $ TorTriGridTD g ps qs d

instance Arbitrary TorTriGridTD where
  arbitrary = sized sizedTorTriGridTD

torTriGridProperties :: [(String, TorTriGridTD -> Property)]
torTriGridProperties = gridProperties "TorTriGrid"
  ++ finiteGridProperties "TorTriGrid"

torTriGridTests :: [Test]
torTriGridTests = makeTests torTriGridProperties


--
-- Toroidal grids with triangular tiles
--

data YCylTriGridTD =
  YCylTriGridTD YCylTriGrid [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData YCylTriGridTD where
  type BaseGrid YCylTriGridTD = YCylTriGrid
  grid (YCylTriGridTD g _ _ _) = g
  points (YCylTriGridTD _ ps _ _) = ps
  twoClosePoints (YCylTriGridTD _ _ qs _) = qs
  neighbourCountBounds _ = (0, 3)
  direction (YCylTriGridTD _ _ _ d) = d

instance TestDataF YCylTriGridTD where
  maxDistance (YCylTriGridTD g _ _ _) = 2*(r+c) - 3
    where (r, c) = size g
  expectedTileCount (YCylTriGridTD g _ _ _) = 2*r*c
    where (r, c) = size g

-- We want the number of tiles in a test grid to be O(n)
sizedYCylTriGridTD :: Int -> Gen YCylTriGridTD
sizedYCylTriGridTD n = do
  r0 <- choose (0,n `div` 2)
  let r = 2*r0
  let c = n `div` (2*r + 1)
  let g = yCylTriGrid r c
  ps <- chooseIndices g n
  qs <- chooseClosePoints g `suchThat` bothValid
  d <- arbitrary
  return $ YCylTriGridTD g ps qs d

instance Arbitrary YCylTriGridTD where
  arbitrary = sized sizedYCylTriGridTD

yCylTriGridProperties :: [(String, YCylTriGridTD -> Property)]
yCylTriGridProperties = gridProperties "YCylTriGrid"
  ++ finiteGridProperties "YCylTriGrid"

yCylTriGridTests :: [Test]
yCylTriGridTests = makeTests yCylTriGridProperties

data XCylTriGridTD =
  XCylTriGridTD XCylTriGrid [(Int,Int)] ((Int,Int),(Int,Int)) TriDirection
  deriving Show

instance TestData XCylTriGridTD where
  type BaseGrid XCylTriGridTD = XCylTriGrid
  grid (XCylTriGridTD g _ _ _) = g
  points (XCylTriGridTD _ ps _ _) = ps
  twoClosePoints (XCylTriGridTD _ _ qs _) = qs
  neighbourCountBounds _ = (0, 3)
  direction (XCylTriGridTD _ _ _ d) = d

instance TestDataF XCylTriGridTD where
  maxDistance (XCylTriGridTD g _ _ _) = 2*(r+c) - 3
    where (r, c) = size g
  expectedTileCount (XCylTriGridTD g _ _ _) = 2*r*c
    where (r, c) = size g

-- We want the number of tiles in a test grid to be O(n)
sizedXCylTriGridTD :: Int -> Gen XCylTriGridTD
sizedXCylTriGridTD n = do
  r0 <- choose (0,n `div` 2)
  let r = 2*r0
  let c = n `div` (2*r + 1)
  let g = xCylTriGrid r c
  ps <- chooseIndices g n
  qs <- chooseClosePoints g `suchThat` bothValid
  d <- arbitrary
  return $ XCylTriGridTD g ps qs d

instance Arbitrary XCylTriGridTD where
  arbitrary = sized sizedXCylTriGridTD

xCylTriGridProperties :: [(String, XCylTriGridTD -> Property)]
xCylTriGridProperties = gridProperties "XCylTriGrid"
  ++ finiteGridProperties "XCylTriGrid"

xCylTriGridTests :: [Test]
xCylTriGridTests = makeTests xCylTriGridProperties

test :: Test
test = testGroup "Math.Geometry.Grid.TriangularQC"
  ( unboundedTriGridTests ++ triTriGridTests ++ paraTriGridTests
    ++ rectTriGridTests ++ torTriGridTests ++ yCylTriGridTests
    ++ xCylTriGridTests)