module Graphics.Autom.NextNearest (grid, overlaidGrid) where
import Prelude ((), (+), mod, Bool, Int, (*), div, undefined, take, map, foldr)
import Data.Vector.Unboxed ((!), Unbox, Vector, length, fromList, generate, concat)
import Data.Word (Word32)
import Data.Bits (testBit, (.|.), shift)
grid :: Vector Bool
-> Word32
-> Int
-> Vector Bool
grid v r h = concat (take h (go v))
where go a = let n = newRow a r in n : go n
overlaidGrid :: Vector Bool
-> Int
-> Vector (Bool, Int)
overlaidGrid v w = fromList (map f [ (r, c)
| r <- [0 .. (rows 1)]
, c <- [0 .. (w 1)] ])
where rows = length v `div` w
f (r, c) = ( indexSeamlessGrid v w (r, c)
, fiveBitInt ( indexSeamlessGrid v w (r 1, c 2)
, indexSeamlessGrid v w (r 1, c 1)
, indexSeamlessGrid v w (r 1, c )
, indexSeamlessGrid v w (r 1, c + 1)
, indexSeamlessGrid v w (r 1, c + 2) ))
newRow :: Vector Bool -> Word32 -> Vector Bool
newRow v r = generate (length v)
(\i -> testBit r (nextNearestInt v i))
fiveBitInt :: (Bool, Bool, Bool, Bool, Bool) -> Int
fiveBitInt (a, b, c, d, e) =
let toi x = if x then 1 else 0 in
foldr (.|.) 0 [ shift (toi a) 4 :: Int
, shift (toi b) 3 :: Int
, shift (toi c) 2 :: Int
, shift (toi d) 1 :: Int
, toi e :: Int ]
indexSeamlessGrid :: Unbox a => Vector a -> Int -> (Int, Int) -> a
indexSeamlessGrid v w (r, c) = v ! i
where i = wr * w + wc
wr = mod r (length v `div` w)
wc = mod c w
wrappedIndex :: Unbox a => Vector a -> Int -> a
wrappedIndex v i = v ! mod i (length v)
nextNearestInt :: Vector Bool -> Int -> Int
nextNearestInt v i = fiveBitInt ( wrappedIndex v (i 2)
, wrappedIndex v (i 1)
, wrappedIndex v i
, wrappedIndex v (i + 1)
, wrappedIndex v (i + 2))