Safe Haskell | None |
---|---|
Language | Haskell98 |
Extras.Cw
Contents
Description
Additional entry points and graphical primitives for CodeWorld.
To use a function defined in this module, you must begin your code with this line:
import Extras.Cw(function)
where instead of function
you write the actual name of the function you
want to use.
You can specifiy more than one function. For example, if you want to use 3
functions, then instead of writing 3 separate import
lines, you can write
this:
import Extras.Cw(function1,function2,function3)
All the functions defined in this module could be implemented directly in CodeWorld, as no internal features of the CodeWorld system are used in their implementation. These functions are provided to save you the tedium of having to add them to your code. To keep this module as small as possible, functions are added to this module only when it has been observed that several people keep adding variations of them to their respective codes.
Synopsis
- between :: (Number, Number, Number, Picture) -> Picture
- beyond :: (Number, Number, Picture) -> Picture
- saw :: (Number, Number) -> Number
- openCurvePoints :: ([Point], Number) -> [Point]
- closedCurvePoints :: ([Point], Number) -> [Point]
- pageFromTexts :: [Text] -> Picture
- grid :: ((Number, Number) -> Picture, Number, Number) -> Picture
- sprite :: (Picture, Number, Number) -> (Number, Number) -> Picture
- overlays :: (Number -> Picture, Number) -> Picture
- underlays :: (Number -> Picture, Number) -> Picture
- squareFrame :: Number -> Picture
- graphed :: (Picture, Number, Number) -> Picture
- wideGraphed :: (Number, Picture, Number, Number) -> Picture
- customGraphed :: (Number, Number, Picture, Number, Number) -> Picture
- data Tree a
- (-<) :: a -> [Tree a] -> Tree a
- treeDepth :: Tree a -> Number
- treeWidth :: Tree a -> Number
- tree :: (Tree a, a -> Picture, Number) -> Picture
- slideshow :: [Picture] -> Program
- autoSlideshow :: ([Picture], Number) -> Program
- randomDrawingOf :: ([Number] -> Picture) -> Program
- randomAnimationOf :: (([Number], Number) -> Picture) -> Program
- randomSlideshow :: ([Number] -> [Picture]) -> Program
- randomAutoSlideshow :: ([Number] -> [Picture], Number) -> Program
Animation convenience functions
between :: (Number, Number, Number, Picture) -> Picture #
The expression between(t,start,stop,drawing)
will show
the given drawing
when the time t
is between start
and stop
beyond :: (Number, Number, Picture) -> Picture #
The expression beyond(t,start,drawing)
will
show the given drawing
when the time t
is beyond the start
time
saw :: (Number, Number) -> Number #
The expression saw(t,p)
is 0
when t=0
, increases up to 1 when t=p/2
, and then decreases back
to 0 when t=p
.
This increasing and decreasing when t
goes from 0
to p
is called
an oscillation of period p
. The oscillations will keep repeating,
so that the function is 0
when t
is 0,p,2p,3p,4p,5p,...
and it is 1 when t
is p/2
, 3p/2
, 5p/2
, 7p/2
, ...
Functions for accessing the points in a curve
openCurvePoints :: ([Point], Number) -> [Point] #
openCurvePoints(controls,distance)
is a list of points that approximate
a curve passing through the given controls
. A variable number of points
is generated in such a way that the distance between them is approximately
the given distance
.
closedCurvePoints :: ([Point], Number) -> [Point] #
This function is similar to openCurvePoints
, but the points approximate
a closed curve passing through the given controls.
Layout
pageFromTexts :: [Text] -> Picture #
A picture that represents the given list of texts, so that each text in the list is shown in a separate line. Lines start at the top left corner of the output window and grow downward. Each line of text can fit 66 characters, and 40 lines can fit in a single page. The lettering is shown in monospaced font.
Example:
program = slideshow(pages) where pages = foreach(gs,pageFromTexts) gs = groups(ls,40) ls = foreach(result,\g -> joinedWith(g,", ")) result = groups(forloop(1,(<= 2000000),(+ 1),printed),7)
The example above shows two million numbers in 7143 pages, so that each
page has 40 lines, each of which has 7 numbers. This example uses
forloop
and foreach
from Extras.Util.
grid :: ((Number, Number) -> Picture, Number, Number) -> Picture #
A grid(cell,rows,columns)
is a grid with the given number of rows
and
columns
, where the rows are numbered top to bottom (top row is row 1)
and the columns are numbered left to right (leftmost column is column 1).
The user needs to specify what to draw at each cell in the grid. The given
function cell
should specify a 20 by 20 picture for each row and column,
where the first argument is the row number, and the second argument is the
column number:
cell(row,col) = fullSizePicture
Each full size picture will be scaled to fit within the corresponding cell.
Look at the example in the documentation of sprite
to see how to use it.
sprite :: (Picture, Number, Number) -> (Number, Number) -> Picture #
A sprite(picture,rows,columns)
creates a function that can be used to
place the given picture
of a sprite into a grid with the given
number of rows
and columns
. The created function needs two
arguments: the row and the column at which you want to show the sprite.
The picture of the sprite should be a full size picture (20x20), which
will be scaled to fit the corresponding cell in the grid.
Example:
import Extras.Cw(saw,grid,sprite) import Extras.Util(printedPoint) program = animationOf(movie) movie(t) = sprite1(row,col) & background where -- Jump between rows 1 and 10 every 100 seconds row = 1 + truncation(10*saw(t,100)) -- Move smoothly between cols 1 and 10 every 10 seconds col = 1 + 9*saw(t,10) sprite1 = sprite(pic,10,10) where pic = rotated(eks,45) eks = solidRectangle(10,1) & solidRectangle(1,10) background = grid(cell,10,10) where cell(row,col) = dilated(lettering(printedPoint(row,col)),5) & rectangle(19,19)
overlays :: (Number -> Picture, Number) -> Picture #
overlays(fig,n)
is a shortcut for fig(1) & fig(2) & ... & fig(n)
underlays :: (Number -> Picture, Number) -> Picture #
underlays(fig,n)
is a shortcut for fig(n) & fig(n-1) & ... & fig(1)
squareFrame :: Number -> Picture #
A white frame around the standard 20x20 output window that covers anything that may spill over. The argument is the thickness of the frame border.
Graphing
graphed :: (Picture, Number, Number) -> Picture #
The given picture scaled by the given scaling factors and shown in a graph that zooms along with the picture. For example, a scaling factor of 2 in either the X direction or the Y direction means that the picture will show twice as big as usual in that direction.
Example 1:
program = animationOf(movie) where movie(t) = let zoom = 1/(1 + t^3) in graphed(circle(5*t^3), zoom, zoom)
Example 2:
program = guiDrawingOf(widgets,draw) where widgets = [ withConversion(zooming, slider("zoomX",-8,9)) , withConversion(zooming, slider("zoomY",-8,7)) ] zooming(v) = 2^(-8 + v*16) draw([zoomX,zoomY]) = graphed(manyCircles, zoomX, zoomY) manyCircles = pictures([circle(n) | n <- [1..100]])
Example 1 shows a circle that grows forever, while the graph keeps
adjusting the scale so that it fits within the output.
Example 2 shows a graph with 100 circles. It uses the function
guiDrawingOf
from Extras.Widget.
wideGraphed :: (Number, Picture, Number, Number) -> Picture #
This function is similar to graphed
, but it creates a graph that is
as wide as specified by the first parameter.
Thus, wideGraphed(width,pic,sx,sy)
creates a graph that is width
units wide and 20
units high.
customGraphed :: (Number, Number, Picture, Number, Number) -> Picture #
This function is similar to graphed
, but it creates a graph that is
as wide and as high as specified by the first two parameters.
Thus, customGraphed(width,height,pic,sx,sy)
creates a graph that
is width
units wide and heighth
units high.
Drawing Trees
A Tree is built by repeated applications of the -<
operator.
Example:
import Extras.Cw((-<),tree,treeDepth,treeWidth) program = drawingOf(picture) where w = 3 picture = tree(t1,draw,w) & translated(lettering(info),5,-9) where draw(node) = lettering(node) & colored(solidRectangle(0.8*w,1),translucent(light(red))) info = joined([ "width: ", printed(treeWidth(t1)) , ", depth: ", printed(treeDepth(t1)) ]) t1 = "hello" -< [ "a" -< [ "a1" -< [] , "a2" -< [] ] , "b" -< [ "b1" -< [ "b11" -< [] , "b12" -< [ "b121" -< [] , "b122" -< [ "b1221" -< [] , "b1222" -< [] , "b1223" -< [] ] ] ] , "b2" -< [ "b21" -< [] , "b22" -< [] , "b23" -< [] ] ] , "c" -< [] , "d" -< [] ]
(-<) :: a -> [Tree a] -> Tree a #
A tree that has the given node at the head and the given list of trees as children nodes.
Example: A binary tree
program = drawingOf(tree(t,\n -> lettering(printed(n)),1.2)) t = 1 -< [ 2 -< [ 4 -< [ 8 -< [ 16 -< [] , 17 -< [] ] , 9 -< [ 18 -< [] , 19 -< [] ] ] , 5 -< [ 10 -< [ 20 -< [] , 21 -< [] ] , 11 -< [ 22 -< [] , 23 -< [] ] ] ] , 3 -< [ 6 -< [ 12 -< [ 24 -< [] , 25 -< [] ] , 13 -< [ 26 -< [] , 27 -< [] ] ] , 7 -< [ 14 -< [ 28 -< [] , 29 -< [] ] , 15 -< [ 30 -< [] , 31 -< [] ] ] ] ]
tree :: (Tree a, a -> Picture, Number) -> Picture #
A Picture of the given tree, where each node is drawn according to the given function. It is assumed that each node is no wider than the given width. Otherwise, overlap between nodes will occur.
New entry points
slideshow :: [Picture] -> Program #
A slide show of the given list of pictures with keyboard and mouse navigation. The following keys can be used to control the slide show:
- Restart the slide show: R
- Go to the next slide: N, space bar, Enter, Page Down
- Go to the previous slide: P, Backspace, Page Up
The given list of pictures must be finite. When the last slide is reached, the slide show will wrap, so that the first slide is shown next. This function cannot be used for showing undelimited step-motion animations.
autoSlideshow :: ([Picture], Number) -> Program #
A slide show that automatically cycles through the list of given pictures. Each picture will be shown for the given number of seconds before advancing to the next picture.
Entry points with randomization
All the randomized versions of entry points provided in this module use the same mechanism to handle random numbers. Before your code runs, the CodeWorld system generates a very large list of random numbers, which is passed to your code. For efficiency, the list is generated on demand, so that only those random numbers actually used in your code are generated. All the random numbers that the system generates are between 0 (included) and 1 (excluded).
Using the randomized versions is very simple. When you click on the output window, the drawing or animation that is currently being shown is replaced with a new one that uses different random numbers. You can keep clicking on your output to see different randomized outputs of your program.
When you write a program that uses the randomized versions, instead of providing a definition of a drawing, you must provide a definition of a function that takes in the list of random numbers as input and generates your drawing as output. Inside your function, you can use as many random numbers as you want.
randomDrawingOf :: ([Number] -> Picture) -> Program #
A randomized version of drawingOf
Example:
program = randomDrawingOf(draw) draw(random) = solidRectangle(width,height) where width = 1 + 9 * random#1 height = 1 + 9 * random#2
The example above will show a different rectangle every time you click on the output. The width and the height will vary randomly between 1 and 10 units.
randomAnimationOf :: (([Number], Number) -> Picture) -> Program #
A randomized version of animationOf
Example:
program = randomAnimationOf(movie) movie(random,t) = rotated(solidRectangle(width,height),45*t) where width = 1 + 9 * random#1 height = 1 + 9 * random#2
The example above will show a random rectangle that rotates around the origin. When you click on the output, a different random rectangle will be shown, which will also be rotating around the origin.
randomAutoSlideshow :: ([Number] -> [Picture], Number) -> Program #
A randomized version of autoSlideshow