Graphics

We will take a look now at some particulars of graphicsIO that are supported by the SOE module.  We can draw upon a window.

The openWindow command creates a window for graphics.

openWindow :: Title -> Size -> IO Window
type Title = String
type Size = (Int,Int)

It should not be difficult to guess what the following program does:  A 300 x 300 pixel window is opened, a greeting message is displayed, and the window is open until the user types a character on the keyboard.

main0= runGraphics (
    do w <- openWindow  "My First Graphics Program" (300,300)
        drawInWindow w (text (100,200) "Hello Graphics World")
        k <- getKey w
        closeWindow w
)

This code introduces the following functions:

runGraphics :: IO() -> IO()         -- runs a graphics action
drawInWindow :: Window -> Graphic -> IO()  -- draws a given Graphic value on a given Window
text :: Point -> String -> Graphic  -- creates a Graphic value consisting of a String whose lower left corner is drawn at the location specified.
getKey :: Window -> IO()  -- waits for the user to press a key
closeWindow :: Window -> IO()  -- closes the window.

Besides drawing text in the window, we have other functions to create Graphic values.

ellispse :: Point -> Point -> Graphic -- draws an ellipse that fits in the given rectangle.
shearEllipse :: Point -> Point -> Point -> Graphic  -- draws an ellispse that fits into a parallelogram
line :: Point -> Point -> Graphic -- draws a line
polyline :: [Point] -> Graphic -- connect each pair of point with lines
polygon :: [Point] -> Graphic -- draws a polygon through the list of points
polyBezier :: [Point] -> Graphic -- like polyline but uses curves to connect the points.

We can also draw in color.  Consider the following example which draws a red ellipse and a blue polyline :

pic1 = withColor Red (ellipse (150,150) (300,200))
pic2 = withColor Blue(polyline [(100,50),(200,50),(200,250),(100,250),(100,50)])

main2 = runGraphics (
    do w <- openWindow "Some Graphics Figures" (300,300)
        drawInWindow w pic1
        drawInWindow w pic2
        spaceClose w
    )

Now for an interesting example.  A mathematical example of a fractal image which is easy to draw is Sierpinski's Triangle.  We first draw a single triangle.  The subdivide the first triangle into three triangles, each half the original size.  Then subdivide each of those triangles in a similar way, repeating ad infinitum. 

                                   

The code for SierpinskiTri is given below.

fillTri :: Window -> Int -> Int -> Int -> IO ()  -- draw a blue filled triangle
fillTri w x y size = drawInWindow w (withColor Blue  (polygon [(x,y),(x+size,y),(x,y-size),(x,y)]))

minSize :: Int
minSize = 8

sierpinskiTri :: Window -> Int -> Int -> Int -> IO ()
sierpinskiTri w x y size =
        if size <= minSize
        then fillTri w x y size
        else let size2 = size `div` 2
                in do sierpinskiTri w x y size2   -- three recursive calls for the subdivide
                          sierpinskiTri w x (y-size2) size2
                          sierpinskiTri w (x+size2) y size2

main4 = runGraphics (
        do w <- openWindow "Sirpinski's Triangle" (400,400)
            drawInWindow w (withColor White (polygon [(0,0),(399,0),(399,399),(0,399)]))
            sierpinskiTri w 50 300 256
            spaceClose w
)