The Pan# User Manual
top | back | next

4  A Tour of the Pan#

In this section we present a brief overview of the Pan# language. File names that end in .pan refer to programs in demos/manual that you should run as you read this section. To see the code in these examples you can use the "View" menu to look at the source code.

4.1  Programs, Expressions, and Definitions

Pan programs are stored in files with the .pan extension. A program may import definitions from another file using an import declaration. An import brings all definitions in an imported file into scope; there is no way to import a subset of the definitions in a file. Local names hide imported names; you can redefine names from imported files or the Prelude.

The statement import foo looks for foo.pan in the directory of the importing file and the library directory, bin, created at installation. There is no way to define a more complex module search path.

There are two sorts of bindings in Pan#.. A definition binds a name to a value while a connection creates a object "outside" of the current image which communicates through the variable on the left of the <-. All connections are made within a frame of reference. Connections at the top level of the program are placed in the full frame of the picture. Imported files cannot have top level connections in them.

This binding creates a slider control and defines x as the current value of the slider:
x <- slider "x" (0, 10) 5

As with ordinary definitions, the ordering of connections doesn't matter. For example, this program:
a <- slider "a" (0, 10) 5
b <- slider "b" (0, 10) 5
picture(x,y) = if (x-a)^2 + (y-b)^2 < 100 then black else white
generates the same images as this one:
b <- slider "b" (0, 10) 5
a <- slider "a" (0, 10) 5
picture(x,y) = if (x-a)^2 + (y-b)^2 < 100 then black else white

4.2  Static Values and Unrolling Loops

Some values in a Pan# program must be static. The control objects such as sliders must be defined using constant parameters. For example, this is not allowed:
x <- slider "One slider" (0,10) 1
y <- slider "Another slider" (x, x+10) 1
This would use the value generated by one slider to set the range of another slider. This program would generate a compile time error since a parameter to the second slider function is not static. The following would be allowed:
x = 10
y <- slider "Another slider" (x, x+10) 1
Since x is a constant, the definition of y is valid.

All loops in a Pan# program must be statically unrollable. That is, indefinite looping is not allowed. The following code is correct since replicate will loop a fixed number of times (3):
replicate n i = if n = 0 then invisibleI 
                         else beside i (replicate (n-1) i)

picture = replicate 3 (colorRegion red $ circle (0,0) 20)
However, this will generate an error at compilation time since the number of iterations cannot be determined at compile time:
replicate n i = if n = 0 then invisibleI 
                         else beside i (replicate (n-1) i)

r <- islider "Number of images" (1,10) 3

picture = replicate r (colorRegion red $ circle (0,0) 20)

4.3  Numeric Functions

Pan# includes a library of standard numeric functions, as described in section 5. There is no type distinction between integral and real numbers in Pan#. Functions which expect integer arguments. mod for example, round any floating point value to the nearest integer. Angles are always expressed in radians rather than degrees. Functions cannot be overloaded - that is, a function or operator can be applied to only one type of object. For example, the + function only adds numbers. An operator for the addition of vectors or matrices would have to have a different name.

4.4  Colors

The built-in colors are shown in examples 01-colors.pan and 02-colors2.pan. Colors can be constructed directly in RGB or HSV space, as shown in example 03-rgbhsv.pan. Arguments to these functions which are out of their expected range give unpredictable results. The program 04-lerpC.pan demonstrates linear color interpolation (the name "lerp" means "linear interpolation", a term from the graphics community). When interpolation generates RGB values outside the range [0,1] results are somewhat odd. The darken and lighten functions interpolate a color toward black or white, as follows:
lightenC x c  = lerpC x c white
darkenC  x c  = lerpC x c black
Colors may be transparent. The fadeC function makes a color more transparent: fadeC 1 leaves the color unchanged and fadeC 0 makes it completely transparent. This is demonstrated in 05-fade.pan.

The withinC function compares the distance in RGB space between two colors. The use of withinC and negC (color negation) is demonstrated in 06-within.pan.

4.5  Strings and Rasters

Strings are used to add text to an image and label controls. The C# format language converts numbers to character strings. Strings can then be converted into rasters (bounded arrays of colors) and thence to continuous images. The conversion from raster to image can be done a number of ways. The default is for "square pixels" (no color interpolation) but bilinear or other interpolation schemes can be used to convert a raster into an continuous image. Interpolation is more computationally demanding and fast conversion from raster to image is usually adequate. The example 07-format.pan uses string concatenation, formatting, and raster to image conversion to interactively show the mouse location. This also demonstrates the default coordinate system: distances are measured in pixels and the origin at the center of the image.

4.6  Functions

Conal Elliott's "Fun of Programming" chapter is the best demonstration of functions and functional images. If you examine the examples in demo/fun against the code in this paper you will see that the code is nearly identical. One of the main differences is that Pan# allows points to be expressed in polar notation, where (r @ theta) denotes a point r from the origin at an angle of theta. This notation can be used in patterns and expressions.

These examples demonstrate the use of regions: functions from 2-D points to booleans. In addition to the operators found in the Fun of Programming chapter there are built-in functions to define a number of basic regions (circles, rectangles, ...) and convert regions into color images. The colorRegion function paints a region with a uniform color, leaving the rest of the image transparent, while colorRegion2 supplies a second color for points outside the region.

4.7  Sized Images

A sized image is an image coupled with a bounding rectangle. String rasterization and the image control (a control that imports a jpeg or gif image into a Pan picture) generate sized images. The bounding box of a sized image can be used to fit these images into a composite picture. A family of functions is provided to move and scale these sized images. The arguments consist of a point, a length, and a sized image. This point is either the target location for the center (C) or the lower left corner (L) of the image. The length may specify the width (W), height (H), or zoom factor (Z) of the image. These images are always scaled uniformly in the X and Y directions. In 08-sizedimages.pan all of the sized image placement functions are shown.

4.8  Frames and Controls

Pan# uses frames to: We will illustrate the use of frames using the following library functions:
slider    :: String -> (Number, Number) -> Number -> Framed Number
beside    :: MFramed ImageC -> MFramed ImageC -> Framed ImageC
zoomIn    :: Number -> MFramed ImageC -> Framed ImageC
These functions operate as follows: The following function creates a slider control and uses it to scale the coordinate system in a given frame:
zoomer :: String -> MFramed ImaceC -> Framed ImageC
zoomer name im = let zoom <- slider name (1,100) 50 in
                    zoomIn zoom im
The first parameter to zoomer is used to label the slider control. The following picture, found in 09-doublezoom.pan, shows two squares side by side, each of which has its own zoom control:
picture = beside (zoomer "Left" square) (zoomer "Right" square)
The MFramed type allows the zoomIn function to be applied to an ordinary image, of type ImageC), or an image within a frame of reference, of type Framed ImageC.

Since the slider function is called twice the resulting image has different sliders.

4.9  Setting the Coordinate System

One way to define the coordinate system in a frame is to specify the coordinates at the frame boundaries. The fit and fitStretch functions adjust the coordinate system so that a given rectangular region, specified by coordinates at the lower left and upper right of the region, fills the frame. The fitStretch function places the rectangular region exactly in the frame while fit scales the coordinate system uniformly and may need to include some area outside the given rectangle. When padding is needed it will always center the view region. The example 10-fit.pan demonstrates these functions. These functions can be used to scale an image to fill a large canvas for the "Save Image" function.

Another way to deal with the coordinate system is to alter the inherited coordinate system by moving the origin or zooming in/out. The functions recenter and lowerLeft are used to translate the coordinate system in a frame while zoomIn and zoomOut scale the coordinate system. With recenter, the coordinate of the point in the center of the frame is specified. Similarly, lowerLeft adjusts the coordinate at the lower left corner of the frame. The example 11-panzoom.pan demonstrates these functions.

The "pixel size" operators return the width or height of a pixel in local coordinates. This functions can create objects whose size does not vary as the coordinate system changes. The program in 12-pixelwidth.pan shows a circle set against an X and Y axis. The axis is drawn to be exactly 4 pixels wide and does not change in width during the zooming.

4.10  Sliders and Check Boxes

A slider produces a number from within a continuous range of values. The value generated by the slider can also be entered directly in the box displaying the slider value. When a value outside the slider's range is entered a dialog box allows the range to be readjusted.

The islider function creates a slider that generates only integers. Aside from that, it is exactly like an ordinary slider. Run the program 13-flower.pan for an example using an integral slider.

The tick function obtains a boolean value rather than numeric value from the user; a "tick" in the box yields "true". The arguments to tick are a label string and the initial state of the box. The example in 14-tickbox.pan shows a tick box in action.

4.11  Imported Images

The image function imports a jpeg/gif file as an image function. The control device allows the user select the particular picture returned by the control. The imported image is centered at (0,0) and is in pixel coordinates. Another function, sizedImage, returns a sized image that can be used with image placement functions. If you want a specific image to appear by default use imageD. You can import a raster rather than a continuous image using imageRaster, allowing more complex image reconstruction algorithms.

The textbox function generates an image by rendering a string. The user enters text and chooses a font and font size. The text is converted to an image which is then returned by the control. As with the image function, there is a sized image version: sizedTextbox. Run 15-labeledpicture.pan for an example using this function.

4.12  The Mouse

The mouse function is a control that observes the mouse position in the coordinate system of the local frame. The mouse position is tracked only when the left button is down. If the mouse is outside the viewing window or the left mouse button is not pressed, the most recently selected location is returned. The example 16-mouseCircle.pan shows how this function works.

A movable point works in much the same way as the mouse except that the actual mouse position is tracked only when the point is in range of the mouse. This allows different movable points in to be controlled separately. Such points need to be visually apparent; there is no special indication on the view window that shows where these points are unless the user invokes the "show movable points" command. A boolean indicates when the point is being dragged; this is normally used to change the appearance of the point. The program 17-rectangle.pan demonstrates the use of movable points.

The coordinates of the initial position for a movable point are in viewer (pixel) coordinates rather than the local frame of reference.

4.13  Timers

Times are used to describe animations. A timer is simply a slider that moves on its own. Timers always start at 0 and increase up to a user-defined limit. When the timer hits the limit it will either stop or resume from zero. The timer menu in the viewer can stop all timers, at which point they become ordinary sliders. The example in 18-rotatingimage.pan shows the use of timers. The "make movie" command in the viewer writes out an animation as a series of numbered image files.

4.14  Random Numbers

The controls randoms and randoms2 generate a 1-D or 2-D function that returns random numbers. Note that a 2-D set of random numbers is similar to an image. The generated random numbers are in the range (0,1). These random functions are defined on integers; non-integral arguments are rounded to the nearest integer. An initial size determines how many different random values are present; this random sequence is repeated outside of the original domain.

4.15  Timing Tracks

A timing track is a sequence of numerically valued events. Tracks are generated by a special version of the Haskore music system are used to create animations that are synchronized to notes in a Haskore score. The getTiming function reads a timing track from a specified file. The findEvent function returns the state of the timing track at a specified time. This state consists of three values: the elapsed time since the last event, the value of the last event, and the duration of the event. A duration of -1 indicates that the event is the last one on the track and thus has infinite duration.

A simple example of timing tracks is found in 20-timings.pan.


The Pan# User Manual
top | back | next |
March, 2004