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"
where body= concatMap show (parse str)
paint' :: [SVG]-> String
paint' 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]