module Main (main) where
-- A vector is a pair of floats
type Vec = (Int, Int)
-- This adds two vectors.
vec_add :: Vec -> Vec -> Vec
(x1,y1) `vec_add` (x2,y2) = (x1+x2, y1+y2)
-- This substracts the second vector from the first.
vec_sub :: Vec -> Vec -> Vec
(x1,y1) `vec_sub` (x2,y2) = (x1-x2, y1-y2)
-- This function is provided for efficiency. The first argument is vector.
-- The second argument and third arguments are integers. These integers
-- represent the nummerator and denominator of a rational number which
-- is used to scale the given vector.
scale_vec2 :: Vec -> Int -> Int -> Vec
scale_vec2 (x,y) a b = ((x*a) `div` b, (y*a) `div` b)
p_tile :: [(Int,Int,Int,Int)]
q_tile :: [(Int,Int,Int,Int)]
r_tile :: [(Int,Int,Int,Int)]
s_tile :: [(Int,Int,Int,Int)]
p_tile =
[(0,3,3,4), (3,4,0,8), (0,8,0,3), (6,0,4,4), (4,5,4,10),
(4,10,7,6), (7,6,4,5), (11,0,10,4), (10,4,9,6), (9,6,8,8), (8,8,4,13),
(4,13,0,16), (0,16,6,15), (6,15,8,16), (8,16,12,12), (12,12,16,12),
(10,16,12,14), (12,14,16,13), (12,16,13,15), (13,15,16,14), (14,16,16,15),
(8,12,16,10), (8,8,12,9), (12,9,16,8), (9,6,12,7), (12,7,16,6),
(10,4,13,5), (13,5,16,4), (11,0,14,2), (14,2,16,2)]
q_tile =
[(0,8,4,7), (4,7,6,7), (6,7,8,8), (8,8,12,10), (12,10,16,16),
(0,12,3,13), (3,13,5,14), (5,14,7,15), (7,15,8,16), (2,16,3,13),
(4,16,5,14), (6,16,7,15), (0,10,7,11), (9,13,8,15), (8,15,11,15),
(11,15,9,13), (10,10,8,12), (8,12,12,12), (12,12,10,10), (2,0,4,5),
(4,5,4,7), (4,0,6,5), (6,5,6,7), (6,0,8,5), (8,5,8,8), (10,0,14,11),
(12,0,13,4), (13,4,16,8), (16,8,15,10), (15,10,16,16), (13,0,16,6),
(14,0,16,4), (15,0,16,2), (0,0,8,0), (12,0,16,0), (0,0,0,8), (0,12,0,16)]
r_tile =
[(0,0,8,8), (12,12,16,16), (0,4,5,10), (0,8,2,12), (0,12,1,14),
(16,6,11,10), (11,10,6,16), (16,4,14,6), (14,6,8,8), (8,8,5,10),
(5,10,2,12), (2,12,0,16), (16,8,12,12), (12,12,11,16), (1,1,4,0),
(2,2,8,0), (3,3,8,2), (8,2,12,0), (5,5,12,3), (12,3,16,0), (11,16,12,12),
(12,12,16,8), (13,13,16,10), (14,14,16,12), (15,15,16,14)]
s_tile =
[(0,0,4,2), (4,2,8,2), (8,2,16,0), (0,4,2,1), (0,6,7,4),
(0,8,8,6), (0,10,7,8), (0,12,7,10), (0,14,7,13), (13,13,16,14),
(14,11,16,12), (15,9,16,10), (16,0,10,4), (10,4,8,6), (8,6,7,8),
(7,8,7,13), (7,13,8,16), (12,16,13,13), (13,13,14,11), (14,11,15,9),
(15,9,16,8), (10,16,11,10), (12,4,10,6), (10,6,12,7), (12,7,12,4),
(15,5,13,7), (13,7,15,8), (15,8,15,5)]
type Line_segment = (Int, Int, Int, Int)
type Picture = Vec -> Vec -> Vec -> [Line_segment]
nil a b c = []
grid :: Int -> Int -> [Line_segment] -> Vec -> Vec -> Vec -> [Line_segment]
grid m n segments a b c
= [tup2
(a `vec_add` (scale_vec2 b x0 m) `vec_add` (scale_vec2 c y0 n))
(a `vec_add` (scale_vec2 b x1 m) `vec_add` (scale_vec2 c y1 n))
| (x0, y0, x1, y1) <- segments]
rot p a b c = p (a `vec_add` b) c ((0, 0) `vec_sub` b)
beside m n p q a b c
= p a (scale_vec2 b m (m+n)) c ++
q (a `vec_add` (scale_vec2 b m (m+n))) (scale_vec2 b n (n+m)) c
above m n p q a b c
= p (a `vec_add` (scale_vec2 c n (m+n))) b (scale_vec2 c m (n+m)) ++
q a b (scale_vec2 c n (m+n))
tup2 :: (a, b) -> (c, d) -> (a, b, c, d)
tup2 (a, b) (c, d) = (a, b, c, d)
tile_to_grid = grid 16 16
p = tile_to_grid p_tile
q = tile_to_grid q_tile
r = tile_to_grid r_tile
s = tile_to_grid s_tile
quartet a b c d = above 1 1 (beside 1 1 a b) (beside 1 1 c d)
t = quartet p q r s
cycle' p1 = quartet p1 (rot (rot (rot p1))) (rot p1) (rot (rot p1))
u = cycle' (rot q)
side1 = quartet nil nil (rot t) t
side2 = quartet side1 side1 (rot t) t
corner1 = quartet nil nil nil u
corner2 = quartet corner1 side1 (rot side1) u
pseudocorner = quartet corner2 side2 (rot side2) (rot t)
pseudolimit = cycle' pseudocorner
nonet p1 p2 p3 p4 p5 p6 p7 p8 p9
= above 1 2 (beside 1 2 p1 (beside 1 1 p2 p3))
(above 1 1 (beside 1 2 p4 (beside 1 1 p5 p6))
(beside 1 2 p7 (beside 1 1 p8 p9)))
corner = nonet corner2 side2 side2 (rot side2) u (rot t) (rot side2) (rot t)
(rot q)
squarelimit = cycle' corner
-- sof: to make it easier to compare outputs, format the vector pairs on sep. lines
fmt [] = "[]"
fmt (x:xs) = (showString "[\n" . showsPrec 0 x . showl xs) ""
where
showl [] s = showChar ']' s
showl (x:xs) s = (showString ",\n" . showsPrec 0 x . showl xs) s
-- SLPJ Nov 99.
-- This showl function used to be curried, but that makes it really
-- hard for GHC to do a good job. Alas, pre 4.05 versions of GHC had a
-- bug that made showl look good. So I've "optimised" it by hand
-- to avoid bizarre comparison numbers
main = putStrLn (fmt (pseudolimit (0, 0) (640, 0) (0,640)))
|