April 11, 2005
A simple generalisation of the 2ser logo
Today I used my implementation of Pan to create a duplicate of the 2ser logo. It's a prime example of a nice effect that should be defined in a language like Pan.
Here it is:

And here's the code:
squareReg :: Frac -> Region
squareReg side (Pt x y) =
let s = side/2
in x > -s && x < s && y > -s && y < s
--
-- Creates a region of circles. The circles are touching
-- and layed out in a square pattern.
--
-- e.g. ***
-- * *
-- ***
-- n denotes the number of circles to a side.
--
-- The top left-hand circle is a postive (True) region. The one next to
-- it is a negative region. This pattern continues around the edge.
--
twoSERReg :: Int -> Frac -> Region
twoSERReg n r =
posReg `diffR` negReg
where
s = (fromIntegral (n-1))*r
-- (-s,-s) is the position of the centre of the top
-- left circle
posReg = foldr1 unionR (map (circleRegAt r) (evens centres))
`unionR` squareReg (2*s)
negReg = foldr1 unionR (map (circleRegAt r) (odds centres))
centreVals = [-s, -s+2*r..s]
centres = [ (Pt x y) | x <- centreVals, y <- centreVals]
circleReg :: Frac -> Region
circleReg r (Pt x y) = (x*x + y*y < r*r)
--
-- Puts the circleReg at a particular point
--
circleRegAt :: Frac -> Point -> Region
circleRegAt r (Pt dx dy) = translate (Vec dx dy) (circleReg r)
twoSER :: Int -> Frac -> ImageC
twoSER n r = colourReg (twoSERReg n r) white blue
effect :: UI DisplayFun
effect = imageToDisplayFun $ do
n <- makeISlider "circles" (1,4) 1
return $ twoSER (2*n+1) 20
evens :: [a] -> [a]
evens = everySnd True
odds = everySnd False
everySnd :: Bool -> [a] -> [a]
everySnd _ [] = []
everySnd True (x:xs) = x:everySnd False xs
everySnd False (x:xs) = everySnd True xs
Of course I coded this so that you could increase the number of circles on each side of the logo using a GUI slider. Increasing the circles from three to five yielded the following cool generalisation of that effect:

How's that for an example of what Pan's capable of?