module Main where import Data.List import Data.Either import Transform import Codec.Picture {- data Transform = Transform {rotate :: Double , scale :: ( Double , Double ) , translate :: ( Double , Double )} -} -- rectangle id width height transformation data SVG= Rec Int Double Double Transform --ellipse id rx ry transformation |El Int Double Double Transform --group id SVGs |G Int [SVG] Transform instance Eq SVG where (Rec id1 w1 h1 _)== (Rec id2 w2 h2 _)= id1==id2 && w1==w2 && h1==h2 (El id1 x1 y1 _) == (El id2 x2 y2 _)= id1== id2 && x1==x2 && y1==y2 (G id1 xs _) == (G id2 ys _)= id1==id2 && xs== ys _ == _ = False show1 :: Transform -> String show1 t= "transform=\"rotate("++(show (rotate t))++") scale("++(show a)++" "++(show b)++") translate("++(show c)++" "++(show d)++")\"" where (a, b)= scale t (c, d)= translate t instance Show SVG where show (Rec id w h t)= " " show (El id rx ry t)= " " show (G id xs t)= " \n"++str++" \n" where str= unlines (map (\x-> " "++(show x)) xs) animate :: [(String, Transform -> Transform)] -> String -> [String] animate [] str = [paint' (parse str)] animate l@((str1,f):ls) str= animate' l xs where xs= parse str animate' :: [(String, Transform -> Transform)] -> [SVG] -> [String] animate' [] xs= [paint' xs] animate' ((str1,f):ls) xs= (paint' xs):(animate' ls ys) where id= read str1::Int ys= animAux xs id f animAux :: [SVG] -> Int -> (Transform -> Transform) -> [SVG] animAux [] i f= [] animAux (g@(G id xs t):ls) i f |id == i= (G id new (f t)):(animAux ls i f) |otherwise= (G id new t):(animAux ls i f) where new= map (\l -> if getId l==i then trans l f else l) xs {- animAux:: [SVG] -> [SVG] -> (Transform -> Transform) -> [[SVG]] animAux _ [] _ = [] animAux xs (y:ys) f= (aux xs y f):(animAux xs ys f) aux:: [SVG] -> SVG -> (Transform -> Transform) -> [SVG] aux [] y f= [] aux (x@(G id ls t):xs) y f |x==y = (G id ls (f t)):xs |y `elem` ls= (G id (map (\l -> if l==y then trans l f else l) ls) t):xs |otherwise= aux xs y f -} trans:: SVG -> (Transform -> Transform)-> SVG trans (Rec id a b t) f= Rec id a b (f t) trans (El id a b t) f= El id a b (f t) {- --return all groups, rectangles and ellipses in the given list of SVGs (list of groups) allObjects :: [SVG] -> [SVG] allObjects [] = [] allObjects ((G id xs t):ls) -} lookupId :: Int -> [SVG]-> [SVG] lookupId i [] = [] lookupId i (g@(G id xs t):ls) |id== i= g:(ys ++(lookupId i ls)) |otherwise= ys ++(lookupId i ls) where ys= filter (\x-> getId x == i) xs getId :: SVG -> Int getId (Rec id _ _ _)= id getId (El id _ _ _)= id getId (G id _ _)= id paint :: String -> String paint str= "\n" ++body++"\n" where body= concatMap show (parse str) paint' :: [SVG]-> String paint' xs= "\n" ++(concatMap show xs)++"\n" parse :: String-> [SVG] parse []= [] parse str= (G grId (map shape shapes) initTrans):(parse rest) where ls= lines str grId= read (init(drop 6(head ls))) ::Int shapes= takeWhile (\x->take 1 x==" ") (tail ls) rest= unlines(tail ls\\shapes) shape :: String -> SVG shape str |take 9 str== " ellipse"= let [x, y, z]= (map (\t-> read t::Double)(words (drop 9 str))) in El (round x) y z initTrans |take 11 str== " rectangle"= let [x, y, z]= (map (\t-> read t::Double)(words (drop 12 str))) in Rec (round x) y z initTrans initTrans :: Transform initTrans= Transform {rotate = 0 , scale =( 1,1 ) , translate = ( 0,0 )} test= "group 1:\n ellipse 2 27.7031 36.4382\n rectangle 1 31.5652 34.9351\ngroup 4:\n ellipse 5 14.5585 38.6296" testb= mapM_ putStrLn $ animate [("1" , mapScale (\( sx , sy ) -> (2 * sx , 0.5 * sy ))) ,("2" , mapRotate (+ 90))] test mapRotate f Transform { rotate =r , scale =s , translate = t } =Transform { rotate = f r , scale =s , translate = t } mapScale f Transform { rotate =r , scale =s , translate = t } =Transform { rotate =r , scale = f s , translate = t } {-WETT-} -- Add any code that generates images or videos between these tags -- Please also include instructions on how to invoke your code -- If you need libraries that are not available on the testserver, send your submission to fpv@in.tum.de --function to create spiral, which rotates i grads spiral :: Int -> Int -> Int -> PixelRGB8 spiral i x y |i<= 0 = PixelRGB8 (fromIntegral (round (r/(0.2*t)))) 0 (fromIntegral (round (r/(0.2*t)/60*(fromIntegral i)))) |otherwise= PixelRGB8 (fromIntegral (round (r/(0.2*t)))) 0 (fromIntegral (round (r/(0.2*t)/60*(fromIntegral i)))) where x'= fromIntegral (x-600) --Double y'= fromIntegral (y-600) --Double r=sqrt $ fromIntegral(round(x'*x' +y'*y') ) -- t= atan (y'/x') +pi/2 +(fromIntegral i)*pi/20 theta= if x'>=0 then atan (y'/x')+ pi/2 + (fromIntegral i)*pi/10 else 3*pi/2 +atan(y'/x') + (fromIntegral i)*pi/10 t= if theta> 2*pi then theta-2*pi else theta --n: Number of generated images- i use 20 spirals :: Int -> [Image PixelRGB8] spirals n |n<=0 = [generateImage (spiral 0) 1200 1200] |otherwise= (generateImage (spiral (20-n)) 1200 1200):(spirals (n-1)) --generate and save Gif using a list of images into the given path --commando: myGen "spiral.gif" (spirals 20) myGen :: FilePath -> [Image PixelRGB8] -> IO() myGen path ls= fromRight (return ()) (writeGifAnimation path 10 (LoopingForever) ls) {-TTEW-} main :: IO () main = do -- path <- getLine savePngImage "new.png" generateImg generateImg :: DynamicImage generateImg = ImageRGB8 (generateImage circle 1200 1200) --generateImg = ImageRGB8 (generateImage func 1200 1200) generateImg' :: DynamicImage generateImg' = ImageRGB8 (generateImage originalFnc 1200 1200) funcPix8 x y= fromIntegral 250 originalFnc :: Int -> Int -> PixelRGB8 originalFnc x y = let (q, r) = x `quotRem` max 10 y s = fromIntegral . min 0xff in PixelRGB8 (s q) (s r) (s (q + r + 30)) func :: Int -> Int -> PixelRGB8 func x y= PixelRGB8 (fromIntegral (round(250 *sin (fromIntegral x/20)) -y)) (fromIntegral y) (fromIntegral (0)) circle :: Int -> Int -> PixelRGB8 circle x y = PixelRGB8 (fromIntegral (round (fromIntegral(x'*x'+y'*y')/200))) 0 (fromIntegral (round (fromIntegral(x'*x'+y'*y')/100))) where x'= x-600 y'= y-600 --circle x y = PixelRGB8 (fromIntegral (round (fromIntegral(x*x+y*y)/50))) 0 (fromIntegral (round (fromIntegral(x*x+y*y)/50))) circle' ::Int -> Int -> Int -> PixelRGB8 circle' i x y |i<=0 =PixelRGB8 (fromIntegral (round (fromIntegral(x'*x'+y'*y')/200))) 0 (fromIntegral (round (fromIntegral(x'*x'+y'*y')/100))) |otherwise = PixelRGB8 (fromIntegral (round (fromIntegral(x'*x'+y'*y' -i*200)/200))) 0 (fromIntegral (round (fromIntegral(x'*x'+y'*y'-i*100)/100))) -- |otherwise = PixelRGB8 (fromIntegral (round (fromIntegral(x'*x'+y'*y' +i*200)/200))) 0 (fromIntegral (round (fromIntegral(x'*x'+y'*y'+i*100)/100))) where x'= x-600 y'= y-600 circles :: Int -> [Image PixelRGB8] circles n |n<=0= [generateImage (circle' 0) 1200 1200] |otherwise= (generateImage (circle' (250-n)) 1200 1200):(circles (n-20)) fGif :: Int -> Int -> Pixel8 fGif x y= (fromIntegral $x+y) foo = writeGifAnimation "new.gif" 10 (LoopingForever) ls where ls= [generateImage func 1200 1200, generateImage originalFnc 1200 1200] f1 i x y= func (x-i) (y) list::Int -> [Image PixelRGB8] list n |n<=0= [generateImage (f1 250) 1200 1200] |otherwise= (generateImage (f1 (250-n)) 1200 1200 ):(list (n-50)) isPrime :: Int -> Bool isPrime n | n <= 1 = False | otherwise = primeAux (n-1) where primeAux 1 = True primeAux i = n `mod` i /= 0 && primeAux (i-1) -- returns all primes up to the passed number primes :: Int -> [Int] primes n = [i | i<-[2..n], isPrime i]