6.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. A frame may be erased with the erase(frame) routine. The functions pair min(frame) and pair max(frame) 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=x,
          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 make the user coordinates of picture pic represent multiples of x units in the x direction and y units in the y direction, use

void unitsize(picture pic=currentpicture, real x, real y=x);

When nonzero, these x and y values override the corresponding size parameters of picture pic.

The routine

void size(picture pic=currentpicture, real xsize, real ysize,
          pair min, pair max);

forces the final picture scaling to map the user coordinates box(min,max) to a region of width xsize and height ysize (when these parameters are nonzero).

Alternatively, calling the routine

transform fixedscaling(picture pic=currentpicture, pair min,
                       pair max, pen p=nullpen, bool warn=false);

will cause picture pic to use a fixed scaling to map user coordinates in box(min,max) to the (already specified) picture size, taking account of the width of pen p. A warning will be issued if the final picture exceeds the specified size.

A picture pic can be fit to a frame and output to a file prefix.format using image format format by calling the shipout function:

void shipout(string prefix=defaultfilename, picture pic=currentpicture,
             orientation orientation=orientation,
             string format="", bool wait=false, bool view=true,
             string options="", string script="",
             light light=currentlight, projection P=currentprojection)

The default output format, PostScript, may be changed with the -f or -tex command-line options. The options, script, and projection parameters are only relevant for 3D pictures. If defaultfilename is an empty string, the prefix outprefix() will be used.

A shipout() command is added implicitly at file exit. Explicit shipout() commands to the same file as the final implicit shipout are ignored. The default page orientation is Portrait; this may be modified by changing the variable orientation. To output in landscape mode, simply set the variable orientation=Landscape or issue the command

shipout(Landscape);

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

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 transformation that would currently be used to fit a picture pic to a frame is returned by the member function pic.calculateTransform().

In certain cases (e.g. 2D graphs) where only an approximate size estimate for pic is available, the picture fitting routine

frame pic.scale(real xsize=this.xsize, real ysize=this.ysize,
                bool keepAspect=this.keepAspect);

(which scales the resulting frame, including labels and fixed-size objects) will enforce perfect compliance with the requested size specification, but should not normally be required.

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:

FillDraw

Fill the interior and draw the boundary.

FillDraw(real xmargin=0, real ymargin=xmargin, pen fillpen=nullpen,

pen drawpen=nullpen) If fillpen is nullpen, fill with the drawing pen; otherwise fill with pen fillpen. If drawpen is nullpen, draw the boundary with fillpen; otherwise with drawpen. An optional margin of xmargin and ymargin can be specified.

Fill

Fill the interior.

Fill(real xmargin=0, real ymargin=xmargin, pen p=nullpen)

If p is nullpen, fill with the drawing pen; otherwise fill with pen p. An optional margin of xmargin and ymargin can be specified.

NoFill

Do not fill.

Draw

Draw only the boundary.

Draw(real xmargin=0, real ymargin=xmargin, pen p=nullpen)

If p is nullpen, draw the boundary with the drawing pen; otherwise draw with pen p. An optional margin of xmargin and ymargin can be specified.

UnFill

Clip the region.

UnFill(real xmargin=0, real ymargin=xmargin)

Clip the region and surrounding margins xmargin and ymargin.

RadialShade(pen penc, pen penr)

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

RadialShadeDraw(real xmargin=0, real ymargin=xmargin, pen penc,

pen penr, pen drawpen=nullpen) Fill with RadialShade and draw the boundary.

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 pen p, using the function bbox(p,Fill).

To pad a picture to a precise size in both directions, fit the picture to a frame using the function

frame pad(picture pic=currentpicture, real xsize=pic.xsize,
          real ysize=pic.ysize, filltype filltype=NoFill);

The functions

pair min(picture pic, user=false);
pair max(picture pic, user=false);
pair size(picture pic, user=false);

calculate the bounds that picture pic would have if it were currently fit to a frame using its default size specification. If user is false the returned value is in PostScript coordinates, otherwise it is in user coordinates.

The function

pair point(picture pic=currentpicture, pair dir, bool user=true);

is a convenient way of determining the point on the bounding box of pic in the direction dir relative to its center, ignoring the contributions from fixed-size objects (such as labels and arrowheads). If user is true the returned value is in user coordinates, otherwise it is in PostScript coordinates.

The function

pair truepoint(picture pic=currentpicture, pair dir, bool user=true);

is identical to point, except that it also accounts for fixed-size objects, using the scaling transform that picture pic would have if currently fit to a frame using its default size specification. If user is true the returned value is in user coordinates, otherwise it is in PostScript coordinates.

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 above=true);
void add(picture dest, picture src, bool group=true,
         filltype filltype=NoFill, bool above=true);

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 should treat all of the elements of src as a single entity (see Graphical User Interface), filltype requests optional background filling or clipping, and above specifies whether to add src above or below existing objects.

There are also routines to add a fixed-size picture or frame src to another picture dest (or currentpicture) about the user coordinate position:

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

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 three 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

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 above=true);
void attach(picture dest=currentpicture, frame src,
                 pair position, pair align, bool group=true,
                 filltype filltype=NoFill, bool above=true);

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 one of the routines

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

Here min and max can be used to specify explicit bounds associated with the resulting PostScript code.

Verbatim TeX commands can be inserted in the intermediate LaTeX output file with one of the functions

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

Here min and max can be used to specify explicit bounds associated with the resulting TeX code.

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, string options="");

provides a convenient abbreviation for

texpreamble("\usepackage["+options+"]{"+s+"}");

that can be used for importing LaTeX packages.