asymptote: Frames and pictures
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' (
label), is returned by
frame align(frame f, pair align);
To draw or fill a box or ellipse around a label or frame and return
the boundary as a path, use one of the predefined 'envelope'
routines
path box(frame f, Label L="", real xmargin=0,
real ymargin=xmargin, pen p=currentpen,
filltype filltype=NoFill, bool above=true);
path roundbox(frame f, Label L="", real xmargin=0,
real ymargin=xmargin, pen p=currentpen,
filltype filltype=NoFill, bool above=true);
path ellipse(frame f, Label L="", real xmargin=0,
real ymargin=xmargin, pen p=currentpen,
filltype filltype=NoFill, bool above=true);
'picture'
Pictures are high-level structures (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 if no
previous 'shipout' commands have been executed. 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)'.
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
'<http://asymptote.sourceforge.net/gallery/.pdf>.asy' should treat
all of the elements of 'src' as a single entity (GUI),
'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 picture or frame 'src' specified
in postscript coordinates 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' (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.