Next: , Previous: Transforms, Up: Programming



4.5 Frames and pictures

frame
Frames are canvases for drawing in PostScript coordinates. While working with frames directly is occasionally necessary for constructing deferred drawing routines, pictures are usually more convenient to work with. The implicit initializer for frames is newframe. The function bool empty(frame f) returns true only if the frame f is empty. The functions pair min(frame f) and pair max(frame f) return the (left,bottom) and (right,top) coordinates of the frame bounding box, respectively. The contents of frame src may be appended to frame dest with the command
     
     void add(frame dest, frame src);
or prepended with
     
     void prepend(frame dest, frame src);
A frame obtained by aligning frame f in the direction align, in a manner analogous to the align argument of label (see label), is returned by
     
     frame align(frame f, pair align);

picture
Pictures are high-level structures (see Structures) defined in the module plain that provide canvases for drawing in user coordinates. The default picture is called currentpicture. A new picture can be created like this:
     
     picture pic;
Anonymous pictures can be made by the expression new picture.

The size routine specifies the dimensions of the desired picture:

     
     void size(picture pic=currentpicture, real x, real y,
               bool keepAspect=Aspect);

If the x and y sizes are both 0, user coordinates will be interpreted as PostScript coordinates. In this case, the transform mapping pic to the final output frame is identity().

If exactly one of x or y is 0, no size restriction is imposed in that direction; it will be scaled the same as the other direction.

If keepAspect is set to Aspect or true, the picture will be scaled with its aspect ratio preserved such that the final width is no more than x and the final height is no more than y.

If keepAspect is set to IgnoreAspect or false, the picture will be scaled in both directions so that the final width is x and the height is y.

To ensure that each dimension is no more than size, use the routine

     
     void size(picture pic=currentpicture, real size,
               bool keepAspect=Aspect);

Alternatively, calling the routine

     
     transform fixedscaling(picture pic=currentpicture, pair min,
                            pair max, pen p=currentpen);
will cause picture pic to use a fixed scaling to map user coordinates in box(min,max) to the (already specified) picture size.

A picture can be fit to a frame and converted into a PostScript image by calling the function shipout:

     
     void shipout(string prefix=defaultfilename, picture pic,
                  real unitsize=0, frame preamble=patterns,
                  orientation orientation=orientation,
                  string format="", bool wait=NoWait, bool quiet=false);
     void shipout(string prefix=defaultfilename, real unitsize=0, 
                  orientation orientation=orientation,
                  string format="", bool wait=NoWait, bool quiet=false);
A shipout() command is added implicitly at file exit if no previous shipout commands have been executed.

A picture pic can be explicitly fit to a frame by calling

     
     frame pic.fit(real xsize=pic.xsize, real ysize=pic.ysize,
                   bool keepAspect=pic.keepAspect);
The default size and aspect ratio settings are those given to the size command (which default to 0, 0, and true, respectively).

The default page orientation is Portrait; this may be modified by changing the variable orientation. To output in landscape mode, simply set orientation=Landscape or issue the command

     
     shipout(Landscape);

To rotate the page by -90 degrees, use the orientation Seascape. To rotate the page by 180 degrees, use the orientation UpsideDown.

To draw a bounding box with margins around a picture, fit the picture to a frame using the function

     
     frame bbox(picture pic=currentpicture, real xmargin=0,
                real ymargin=xmargin, pen p=currentpen,
                filltype filltype=NoFill);
Here filltype specifies one of the following fill types:
Fill
Fill with the pen used to draw the boundary.
Fill(pen p=nullpen)
If p is nullpen, fill with the pen used to draw the boundary; otherwise fill with pen p.


NoFill
Do not fill; draw only the boundary.


UnFill
Clip the region.


UnFill
Clip the region and surrounding margins xmargin and ymargin.


RadialShade
Fill varying radially from penc at the center of the bounding box to penr at the edge.

For example, to draw a bounding box around a picture with a 0.25 cm margin and output the resulting frame, use the command:

     
     shipout(bbox(0.25cm));
A picture may be fit to a frame with the background color of pen p with the function bbox(p,Fill).

The functions

     
     pair min(picture pic);
     pair max(picture pic);
calculate the PostScript bounds that picture pic would have if it were currently fit to a frame using its default size specification.

The function

     
     pair point(picture pic=currentpicture, pair dir);
is a convenient way of determining the point on the boundary of the user-coordinate bounding box of pic in the direction dir relative to its center. The function
     
     pair truepoint(picture pic=currentpicture, pair dir);
works similarly, except the result is a point on the true picture bounding box that picture pic would have if it were currently fit to a frame using its default size specification.

Sometimes it is useful to draw objects on separate pictures and add one picture to another using the add function:

     
     void add(picture src, bool group=true,
              filltype filltype=NoFill, bool put=Above);
     void add(picture dest, picture src, bool group=true,
              filltype filltype=NoFill, bool put=Above);

The first example adds src to currentpicture; the second one adds src to dest. The group option specifies whether or not the graphical user interface xasy should treat all of the elements of src as a single entity (see GUI), filltype requests optional background filling or clipping, and put specifies whether to add src above or below existing objects.

There are also routines to add a picture or frame src specified in postscript coordinates to another picture about the user coordinate position:

     
     void add(picture dest, picture src, pair position, bool group=true,
              filltype filltype=NoFill, bool put=Above);
     void add(picture src, bool group=true, pair position,
              filltype filltype=NoFill, bool put=Above);
     void add(picture dest=currentpicture, frame src, pair position=0,
              bool group=true, filltype filltype=NoFill,
              bool put=Above);
     void add(picture dest=currentpicture, frame src, pair position,
              pair align, bool group=true, filltype filltype=NoFill,
              bool put=Above);

The optional align argument in the last form specifies a direction to use for aligning the frame, in a manner analogous to the align argument of label (see label). However, one key difference is that when align is not specified, labels are centered, whereas frames and pictures are aligned so that their origin is at position. Illustrations of frame alignment can be found in the examples errorbars and image. If you want to align 3 or more subpictures, group them two at a time:

     picture pic1;
     real size=50;
     size(pic1,size);
     fill(pic1,(0,0)--(50,100)--(100,0)--cycle,red);
     
     picture pic2;
     size(pic2,size);
     fill(pic2,unitcircle,green);
     
     picture pic3;
     size(pic3,size);
     fill(pic3,unitsquare,blue);
     
     picture pic;
     add(pic,pic1.fit(),(0,0),N);
     add(pic,pic2.fit(),(0,0),10S);
     
     add(pic.fit(),(0,0),N);
     add(pic3.fit(),(0,0),10S);
     
subpictures.png

Alternatively, one can use attach to automatically increase the size of picture dest to accommodate adding a frame src about the user coordinate position:

     
     void attach(picture dest=currentpicture, frame src,
                 pair position=0, bool group=true,
                 filltype filltype=NoFill, bool put=Above);
     void attach(picture dest=currentpicture, frame src,
                 pair position=0, pair align, bool group=true,
                 filltype filltype=NoFill, bool put=Above);

To draw or fill a box or ellipse around a label, frame, or picture, use one of the routines (the first two routines for convenience also return the boundary as a guide):

     
     guide box(frame f, Label L="", real xmargin=0,
               real ymargin=xmargin, pen p=currentpen,
               filltype filltype=NoFill, bool put=Above);
     guide ellipse(frame f, Label L="", real xmargin=0,
                   real ymargin=xmargin, pen p=currentpen,
                   filltype filltype=NoFill, bool put=Above);
     void box(picture pic=currentpicture, Label L,
              real xmargin=0, real ymargin=xmargin, pen p=currentpen,
              filltype filltype=NoFill, bool put=Above);

To erase the contents of a picture (but not the size specification), use the function

     
     void erase(picture pic=currentpicture);

To save a snapshot of currentpicture, currentpen, and currentprojection, use the function save().

To restore a snapshot of currentpicture, currentpen, and currentprojection, use the function restore().

Many further examples of picture and frame operations are provided in the base module plain.

It is possible to insert verbatim PostScript commands in a picture with the routine

     
     void postscript(picture pic=currentpicture, string s);

Verbatim TeX commands can be inserted in the intermediate LaTeX output file with the function

     
     void tex(picture pic=currentpicture, string s);

To issue a global TeX command (such as a TeX macro definition) in the TeX preamble (valid for the remainder of the top-level module) use:

     
     void texpreamble(string s);

The TeX environment can be reset to its initial state, clearing all macro definitions, with the function

     
     void texreset();

The routine

     
     void usepackage(string s);
is a convenient abbreviation for texpreamble("\usepackage{"+s+"}"); that can be used for importing LaTeX packages.