import Graphics.SOE

{-- Einige Definitionen aus der 
    SOE (School of Expression-Buch) Graphik Bibliothek 



type Title   =  String
-- Fenstergroesse in Pixeln
type Size    =  (Int,Int)

-- Durchfuehrung einer Graphikausgabe
runGraphics  :: IO () -> IO ()

-- Oeffnen und Schliessen von Fenstern 
openWindow   :: Title -> Size -> IO Window
closeWindow  :: Window -> IO ()

-- Ausgabe einer Graphik in einem Fenster
drawInWindow :: Window -> Graphic -> IO ()

-- Tastatureingabe in einem Fenster
getKey       :: Window -> IO Char

-----------------------------------------------------------}


-- Öffnen und Schließen eines Fensters 
openCloseWindow :: IO ()
openCloseWindow =  runGraphics (
                    do  w <- openWindow "My Window" (300,300)
                        k <- getKey w  -- warte auf Tastatureingabe
                        closeWindow w
                   )
                   
{-- Vordefinierte Graphiken --------------------------------
                   
-- Pixelkoordinaten 
type Point   =  (Int,Int)

-- Definition einfacher Graphiken
text         :: Point -> String -> Graphic
line         :: Point -> Point  -> Graphic
polyline     :: [Point]         -> Graphic
polygon      :: [Point]         -> Graphic
ellipse      :: Point -> Point  -> Graphic

-- Faerben von Graphiken
data Color   =  Black  | Blue    | Green  | Cyan
              | Red    | Magenta | Yellow | White

withColor    :: Color -> Graphic -> Graphic 

-------------------------------------------------------------}                   

bild :: IO () 
bild =  runGraphics (
         do  w <- openWindow "Bild" (400,400)
             drawInWindow w (withColor Yellow 
              (polygon [(100,100),(100,300),(300,300),(300,100)]))
             drawInWindow w (withColor Red 
              (ellipse (150,150) (250,250)))
             drawInWindow w (withColor Red 
              (text (140,50) " Kreis im Rechteck "))
             spaceClose w
                    )


-- Schließen eines Fensters durch Leertaste 
spaceClose   :: Window -> IO ()
spaceClose w =  do  k <- getKey w
                    if k == ' ' then closeWindow w
                                else spaceClose w                    
                                
                                

{-----------------------------------------------------------------                                

	Sierpinski Dreiecke 
	
------------------------------------------------------------------}	

triangle :: Window -> Point -> Int -> Color -> IO ()
triangle w (x,y) size color 
    = drawInWindow w (withColor color
            (polygon [(x,y),(x+size,y),(x,y-size)]))




minSize :: Int 
minSize =  8   -- minimale Dreieckgroesse

-- Definition eines Sierpinski Dreiecks
sierpinski :: Window -> Point -> Int -> Color -> IO ()
sierpinski w p size c 
    = if size <= minSize then triangle w p size c
      else let size2 = size `div` 2
               (x,y) = p
           in  do   sierpinski w p size2 c
                    sierpinski w (x,y-size2) size2 c
                    sierpinski w (x+size2,y) size2 c

-- Bildschirmausgabe 
sierpinskiTriangle = runGraphics (
    do  w <- openWindow "Sierpinski Dreieck" (600,600)
        sierpinski w (50,550) 512 Yellow
        spaceClose w
    )
    


{---------------------------------------------------------------------

	Schneeflocke 
	
---------------------------------------------------------------------}	    
    

m = 81  :: Int -- multiple of 3 for triangle size
x = 250 :: Int -- x and y coordinates of
y = 250 :: Int --         center of snowflake
colors = [ White, Yellow, Blue, Green, Red ]
noColors = repeat White

snowflake :: Window -> IO ()
snowflake w = do
  drawTri w x y m 0 False -- draw first triangle w/flat top
  flake   w x y m 0 True  -- begin recursion to complete job

flake :: Window -> Int -> Int -> Int -> Int -> Bool -> IO ()
flake w x y m c o = do
   drawTri w x y m c o  -- draw second triangle
   let c1 = (c+1)`mod`5 -- get next color
   if (m<=3) then return ()  -- if too small, we're done
      else do
        flake w (x-2*m) (y-m) (m`div`3) c1 True  -- NW
        flake w (x+2*m) (y-m) (m`div`3) c1 True  -- NE
        flake w  x    (y+2*m) (m`div`3) c1 True  -- S
        flake w (x-2*m) (y+m) (m`div`3) c1 False -- SW
        flake w (x+2*m) (y+m) (m`div`3) c1 False -- SE
        flake w  x    (y-2*m) (m`div`3) c1 False -- N

drawTri :: Window -> Int -> Int -> Int -> Int -> Bool -> IO ()
drawTri w x y m c o =
   let d =  (3*m) `div` 2
       ps = if o
            then [(x,y-3*m),  (x-3*m,y+d), (x+3*m,y+d)] -- side at bottom
            else [ (x,y+3*m), (x-3*m,y-d), (x+3*m,y-d)] -- side at top
   in drawInWindow w
        (withColor (colors !! c)
           (polygon ps))
main
  = runGraphics (
     do w <- openWindow "Snowflake Fractal" (500,500)
        drawInWindow w (withColor Red
          (polygon [(0,0),(499,0),(499,499),(0,499)]) )
        snowflake w
        spaceClose w
     )
    