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:

2ser.png

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:

2ser-generalisation.png

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