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' (See
      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 (SeeStructures) 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 (SeeGUI),
      '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' (Seelabel).  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 Seeerrorbars and Seeimage.  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.