[comp.sources.amiga] v90i009: plplot 2.6 - C library for making scientific plots, Part08/12

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (01/15/90)

Submitted-by: Anthony M. Richardson <amr@dukee.egr.duke.edu>
Posting-number: Volume 90, Issue 009
Archive-name: applications/plplot-2.6/part08

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 12)."
# Contents:  Amiga/plmenu.c docs/chapter3.tex
# Wrapped by tadguy@xanth on Sun Jan 14 18:11:55 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Amiga/plmenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Amiga/plmenu.c'\"
else
echo shar: Extracting \"'Amiga/plmenu.c'\" \(16175 characters\)
sed "s/^X//" >'Amiga/plmenu.c' <<'END_OF_FILE'
X#include "plplot.h"
X#include "plamiga.h"
X#include <math.h>
X
Xvoid eventwait()
X{
X   for(;;) {
X      /* Wait for message */
X      Wait(1<<PLWindow->UserPort->mp_SigBit);
X      if(procmess())
X         return;
X   }
X}
X
XPLINT procmess()
X{
X   ULONG class;
X   USHORT code;
X   struct IntuiMessage *message;
X
X   while(message = (struct IntuiMessage *)GetMsg(PLWindow->UserPort)) {
X      class = message->Class;
X      code = message->Code;
X      ReplyMsg((struct Message *)message);
X      if(eventhandler(class,code))
X         return((PLINT)1);
X   }
X   return((PLINT)0);
X}
X
XPLINT eventhandler(class, code)
XULONG class;
XUSHORT code;
X{
X   switch (class) {
X      case CLOSEWINDOW:
X         return((PLINT)1);
X      case MENUPICK:
X         menuselect(class,code);
X         break;
X      case SIZEVERIFY:
X         break;
X      case NEWSIZE:
X         if(!(PLCurPrefs.WinType & PLCUST)) {
X            PLCurPrefs.WWidth = PLWindow->Width;
X            PLCurPrefs.WHeight = PLWindow->Height;
X         }
X         else {
X            PLCurPrefs.CWidth = PLWindow->Width;
X            PLCurPrefs.CHeight = PLWindow->Height;
X         }
X         setlimits();
X         disablegads(0);
X         disablemenus();
X         remakeplot();
X         enablemenus();
X         enablegads();
X         break;
X      default:
X         break;
X   }
X
X   return((PLINT)0);
X}
X
Xstruct IntuiText IText0ItemScrSubs[] = {
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"WorkBench", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Custom", NULL}
X};
X
Xstruct MenuItem Menu0ItemScrSubs[] = {
X   {
X      &Menu0ItemScrSubs[1],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT,
X      0xFFFE,
X      (APTR)&IText0ItemScrSubs[0],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      NULL,
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT,
X      0xFFFD,
X      (APTR)&IText0ItemScrSubs[1],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   }
X};
X
Xstruct IntuiText IText0ItemPriSubs[] = {
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Bitmap Dump", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Full Page (Landscape)", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Full Page (Portrait)", NULL}
X};
X
Xstruct MenuItem Menu0ItemPriSubs[] = {
X   {
X      &Menu0ItemPriSubs[1],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      NULL,
X      (APTR)&IText0ItemPriSubs[0],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu0ItemPriSubs[2],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      NULL,
X      (APTR)&IText0ItemPriSubs[1],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      NULL,
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      NULL,
X      (APTR)&IText0ItemPriSubs[2],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   }
X};
X
Xstruct IntuiText IText0[] = {
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Save Configuration",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Reset",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Maintain Plot Aspect",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Redraw Enabled",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Select Screen Type",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Print",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Save Bitmap as IFF file",NULL}
X};
X
Xstruct MenuItem Menu0Items[] = {
X   {
X      &Menu0Items[1],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText0[0],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu0Items[2],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText0[1],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu0Items[3],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | MENUTOGGLE,
X      0,
X      (APTR)&IText0[2],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu0Items[4],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | MENUTOGGLE,
X      0,
X      (APTR)&IText0[3],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu0Items[5],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText0[4],
X      NULL,
X      NULL,
X      &Menu0ItemScrSubs[0],
X      NULL
X   },
X   {
X      &Menu0Items[6],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText0[5],
X      NULL,
X      NULL,
X      &Menu0ItemPriSubs[0],
X      NULL
X   },
X   {
X      NULL,
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText0[6],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   }
X};
X
Xstruct IntuiText IText1Item2Subs[] = {
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)" 2", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)" 4", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)" 8", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"16", NULL}
X};
X
Xstruct MenuItem Menu1Item2Subs[] = {
X   {
X      &Menu1Item2Subs[1],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT,
X      0xFFFE,
X      (APTR)&IText1Item2Subs[0],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu1Item2Subs[2],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT,
X      0xFFFD,
X      (APTR)&IText1Item2Subs[1],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu1Item2Subs[3],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT,
X      0xFFFB,
X      (APTR)&IText1Item2Subs[2],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      NULL,
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT,
X      0xFFF7,
X      (APTR)&IText1Item2Subs[3],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   }
X};
X
Xstruct IntuiText IText1[] = {
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Interlaced", NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"High Resolution",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Number of Colors",NULL},
X   {0, 1, JAM1, 0, 0, NULL, (UBYTE *)"Set Color Palette",NULL}
X};
X
X
Xstruct MenuItem Menu1Items[] = {
X   {
X      &Menu1Items[1],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | MENUTOGGLE,
X      0,
X      (APTR)&IText1[0],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu1Items[2],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | MENUTOGGLE,
X      0,
X      (APTR)&IText1[1],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   },
X   {
X      &Menu1Items[3],
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText1[2],
X      NULL,
X      NULL,
X      &Menu1Item2Subs[0],
X      NULL
X   },
X   {
X      NULL,
X      0, 0, 0, 0,
X      ITEMTEXT | ITEMENABLED | HIGHCOMP,
X      0,
X      (APTR)&IText1[3],
X      NULL,
X      NULL,
X      NULL,
X      NULL
X   }
X};
X
Xstruct Menu Menu[] = {
X   {
X      &Menu[1],
X      0, 0, 0, 0,
X      MENUENABLED,
X      "PLPlot",
X      &Menu0Items[0]
X   },
X   {
X      NULL,
X      0, 0, 0, 0,
X      MENUENABLED,
X      "Screen Format",
X      &Menu1Items[0]
X   }
X};
X
Xenum menus { PLMCONTROL, PLMSCREEN };
X
X/* Control menu items */
Xenum menu0items { PLMSAVECONFIG, PLMRECONFIG, PLMASPECT, PLMBUFF,
X                  PLMSCREENTYPE, PLMSCRDUMP, PLMSIFF };
Xenum menu0itemscrsubs { PLMWBENCH, PLMCUSTOM };
Xenum menu0itemprisubs { PLMPRWIN, PLMPRPLAN, PLMPRPPOR };
X
X/* Custom screen menu items */
Xenum menu1items { PLMLACE, PLMHIRES, PLMCOLORS, PLMCOLREQ };
X/* Number color subitems */
Xenum menu1item2subs {PLMC2, PLMC4, PLMC8, PLMC16 };
X
Xvoid MakePLMenu()
X{
X   short mtx, mledge;
X   short itx, itxlen, itedge, ichk;
X   short stx, stxlen, stedge, schk;
X   short fheight;
X   char *string;
X   struct Menu *menu;
X   struct MenuItem *item, *subitem;
X   struct IntuiText *itext;
X
X   fheight = PLScreen->Font->ta_YSize;
X
X   if(PLCurPrefs.WinType & PLCUST)
X      Menu[0].NextMenu = &Menu[1];
X   else
X      Menu[0].NextMenu = NULL;
X
X   mledge = 0;
X   for(menu=Menu; menu!=NULL; menu=menu->NextMenu) {
X      string = (char *)menu->MenuName;
X      mtx = (short)TextLength(PLSRPort,string,(long)strlen(string));
X      /* Leave two character space between menus */
X      mtx += (2*mtx)/strlen(string);
X      menu->LeftEdge = mledge;
X      menu->Width = mtx;
X      mledge += mtx;
X
X      /* Find length of longest menuitem in this menu */
X      itxlen = 0;
X      ichk = 0;
X      for(item=menu->FirstItem; item!=NULL; item=item->NextItem) {
X         itext = (struct IntuiText *)item->ItemFill;
X         string = (char *)itext->IText;
X         itx = (short)TextLength(PLSRPort,string,(long)strlen(string));
X         itxlen = max(itxlen,itx);
X         if(item->Flags & CHECKIT)
X            ichk = 1;
X      }
X      itedge = 0;
X      for(item=menu->FirstItem; item!=NULL; item=item->NextItem) {
X         item->Width = itxlen;
X         item->LeftEdge = 0;
X         item->TopEdge = itedge;
X         item->Height = fheight;
X         if(ichk) {
X            item->Width += CHECKWIDTH;
X            itext = (struct IntuiTest *)item->ItemFill;
X            itext->LeftEdge = CHECKWIDTH;
X         }
X         itedge += fheight;
X         stxlen = 0;
X         schk = 0;
X         for(subitem=item->SubItem;subitem!=NULL;subitem=subitem->NextItem){
X            itext = (struct IntuiText *)subitem->ItemFill;
X            string = (char *)itext->IText;
X            stx = (short)TextLength(PLSRPort,string,(long)strlen(string));
X            stxlen = max(stxlen,stx);
X            if(subitem->Flags & CHECKIT)
X               schk = 1;
X         }
X         stedge = 0;
X         for(subitem=item->SubItem;subitem!=NULL;subitem=subitem->NextItem){
X            subitem->Width = stxlen;
X            subitem->LeftEdge = item->Width/2;
X            subitem->TopEdge = stedge;
X            subitem->Height = fheight;
X            if(schk) {
X               subitem->Width += CHECKWIDTH;
X               itext = (struct IntuiTest *)subitem->ItemFill;
X               itext->LeftEdge = CHECKWIDTH;
X            }
X            stedge += fheight;
X         }
X      }
X   }
X
X   if(PLCurPrefs.WinType & PLCUST) {
X      Menu0ItemScrSubs[PLMCUSTOM].Flags |= CHECKED;
X      Menu0ItemScrSubs[PLMWBENCH].Flags &= ~CHECKED;
X      Menu1Items[PLMLACE].Flags |= ITEMENABLED;
X      Menu1Items[PLMHIRES].Flags |= ITEMENABLED;
X      Menu1Items[PLMCOLORS].Flags |= ITEMENABLED;
X   }
X   else {
X      Menu0ItemScrSubs[PLMCUSTOM].Flags &= ~CHECKED;
X      Menu0ItemScrSubs[PLMWBENCH].Flags |= CHECKED;
X   }
X
X   Menu1Item2Subs[PLMC2].Flags &= ~CHECKED;
X   Menu1Item2Subs[PLMC4].Flags &= ~CHECKED;
X   Menu1Item2Subs[PLMC8].Flags &= ~CHECKED;
X   Menu1Item2Subs[PLMC16].Flags &= ~CHECKED;
X   Menu1Item2Subs[PLCurPrefs.Depth-1].Flags |= CHECKED;
X
X   if(PLCurPrefs.ScrType & PLLACE)
X      Menu1Items[PLMLACE].Flags |= CHECKED;
X   else
X      Menu1Items[PLMLACE].Flags &= ~CHECKED;
X
X   if(PLCurPrefs.ScrType & PLHIRES)
X      Menu1Items[PLMHIRES].Flags |= CHECKED;
X   else
X      Menu1Items[PLMHIRES].Flags &= ~CHECKED;
X
X   if(PLCurPrefs.WinType & PLASP)
X      Menu0Items[PLMASPECT].Flags |= CHECKED;
X   else
X      Menu0Items[PLMASPECT].Flags &= ~CHECKED;
X
X   if(PLCurPrefs.WinType & PLBUFF)
X      Menu0Items[PLMBUFF].Flags |= CHECKED;
X   else
X      Menu0Items[PLMBUFF].Flags &= ~CHECKED;
X
X   SetMenuStrip(PLWindow,Menu);
X}
X
Xvoid disablemenus()
X{
X   OffMenu(PLWindow, PLMCONTROL | SHIFTITEM(NOITEM));
X   OffMenu(PLWindow, PLMSCREEN  | SHIFTITEM(NOITEM));
X}
X
Xvoid enablemenus()
X{
X   OnMenu(PLWindow, PLMCONTROL | SHIFTITEM(NOITEM));
X   OnMenu(PLWindow, PLMSCREEN  | SHIFTITEM(NOITEM));
X}
X
Xvoid menuselect(class, code)
XULONG class;
XUSHORT code;
X{
X   PLINT ItemNumber, MenuNumber, SubNumber;
X   PLINT remake=0;
X   struct MenuItem *Item;
X
X   if(class == VANILLAKEY)
X      ;
X   else if(class == MENUPICK) {
X      while(code != MENUNULL) {
X         Item = ItemAddress(Menu,code);
X         MenuNumber = MENUNUM(code);
X         ItemNumber = ITEMNUM(code);
X         SubNumber = SUBNUM(code);
X         if(MenuNumber == PLMCONTROL) {
X            if(ItemNumber == PLMSAVECONFIG) {
X               if(!(PLCurPrefs.WinType & PLCUST)) {
X                  PLCurPrefs.WXPos = PLWindow->LeftEdge;
X                  PLCurPrefs.WYPos = PLWindow->TopEdge;
X               }
X               else {
X                  PLCurPrefs.CXPos = PLWindow->LeftEdge;
X                  PLCurPrefs.CYPos = PLWindow->TopEdge;
X               }
X               SetPLDefs();
X            }
X            else if(ItemNumber == PLMRECONFIG) {
X               RestorePrefs();
X               remake = 1;
X            }
X            else if(ItemNumber == PLMASPECT) {
X               if(Item->Flags & CHECKED) {
X                  PLCurPrefs.WinType |= PLASP;
X               }
X               else {
X                  PLCurPrefs.WinType &= ~PLASP;
X               }
X               setlimits();
X               disablegads(0);
X               disablemenus();
X               remakeplot();
X               enablemenus();
X               enablegads();
X            }
X            else if(ItemNumber == PLMBUFF) {
X               if(Item->Flags & CHECKED) {
X                  PLCurPrefs.WinType |= PLBUFF;
X               }
X               else {
X                  PLCurPrefs.WinType &= ~PLBUFF;
X               }
X            }
X            else if(ItemNumber == PLMSCREENTYPE) {
X               if(SubNumber == PLMWBENCH) {
X                  if(!(PLCurPrefs.WinType & PLCUST)) goto reselect;
X                  PLCurPrefs.CXPos = PLWindow->LeftEdge;
X                  PLCurPrefs.CYPos = PLWindow->TopEdge;
X                  PLCurPrefs.WinType &= ~PLCUST;
X               }
X               else if(SubNumber == PLMCUSTOM) {
X                  if(PLCurPrefs.WinType & PLCUST) goto reselect;
X                  /* Save wbench window position */
X                  PLCurPrefs.WXPos = PLWindow->LeftEdge;
X                  PLCurPrefs.WYPos = PLWindow->TopEdge;
X                  PLCurPrefs.WinType |= PLCUST;
X               }
X               remake = 1;
X            }
X            else if(ItemNumber == PLMSCRDUMP) {
X               /* Disable system gadgets */
X               disablegads(SubNumber);
X               disablemenus();
X               screendump(SubNumber);
X               enablemenus();
X               enablegads();
X            }
X            else if(ItemNumber == PLMSIFF) {
X               disablegads(0);
X               disablemenus();
X               saveiff();
X               enablemenus();
X               enablegads();
X            }
X         }
X         else if(MenuNumber == PLMSCREEN) {
X            if(ItemNumber == PLMLACE) {
X               if(Item->Flags & CHECKED)
X                  PLCurPrefs.ScrType |= PLLACE;
X               else
X                  PLCurPrefs.ScrType &= ~PLLACE;
X               PLCurPrefs.CWidth = 0;
X               PLCurPrefs.CHeight = 0;
X               remake = 1;
X            }
X            else if(ItemNumber == PLMHIRES) {
X               if(Item->Flags & CHECKED)
X                  PLCurPrefs.ScrType |= PLHIRES;
X               else
X                  PLCurPrefs.ScrType &= ~PLHIRES;
X               PLCurPrefs.CWidth = 0;
X               PLCurPrefs.CHeight = 0;
X               remake = 1;
X            }
X            else if(ItemNumber == PLMCOLORS) {
X               if(SubNumber == PLMC2) {
X                  if(PLCurPrefs.Depth == 1) goto reselect;
X                  PLCurPrefs.Depth = 1;
X               }
X               else if(SubNumber == PLMC4) {
X                  if(PLCurPrefs.Depth == 2) goto reselect;
X                  PLCurPrefs.Depth = 2;
X               }
X               else if(SubNumber == PLMC8) {
X                  if(PLCurPrefs.Depth == 3) goto reselect;
X                  PLCurPrefs.Depth = 3;
X               }
X               else if(SubNumber == PLMC16) {
X                  if(PLCurPrefs.Depth == 4) goto reselect;
X                  PLCurPrefs.Depth = 4;
X               }
X               PLCurPrefs.CXPos = PLWindow->LeftEdge;
X               PLCurPrefs.CYPos = PLWindow->TopEdge;
X               remake = 1;
X            }
X            else if(ItemNumber == PLMCOLREQ) {
X               disablegads(1);
X               disablemenus();
X               plcolreq();
X               enablemenus();
X               enablegads();
X            }
X         }
Xreselect:
X         code = Item->NextSelect;
X      }
X   }
X   if(remake) {
X      ClosePLWind();
X      OpenPLWind();
X      setlimits();
X      disablegads(0);
X      disablemenus();
X      remakeplot();
X      enablemenus();
X      enablegads();
X   }
X}
X
END_OF_FILE
if test 16175 -ne `wc -c <'Amiga/plmenu.c'`; then
    echo shar: \"'Amiga/plmenu.c'\" unpacked with wrong size!
fi
# end of 'Amiga/plmenu.c'
fi
if test -f 'docs/chapter3.tex' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'docs/chapter3.tex'\"
else
echo shar: Extracting \"'docs/chapter3.tex'\" \(24805 characters\)
sed "s/^X//" >'docs/chapter3.tex' <<'END_OF_FILE'
X\chapter {Advanced Use of PLPLOT}\label{advanced}
X
XIn this chapter, we describe more precisely how to control the position
Xand scaling of a graph, how to alter the low-level line and character
Xattributes, and how to use the functions in PLPLOT for drawing
Xthree-dimensional surface plots and contour plots.
X
X\section {Basic PLPLOT Concepts}
X
XWhen drawing a graph, the programmer usually wishes to specify the
Xcoordinates of the points to be plotted in terms of the values of the
Xvariables involved. These coordinates are called {\em world
Xcoordinates}, and may have any floating-point value representable by the
Xcomputer. The {\em window} refers to the rectangular region of
Xworld-coordinate space which is to be graphed. This window is mapped
Xonto a rectangular region of the {\em view surface}, which is (a
Xportion) of the screen or sheet of paper in the output device. This
Xphysical region onto which the window is mapped is called the {\em
Xviewport}. Before a graph can be drawn, the program must define both the
Xwindow and the viewport by calling appropriate routines in PLPLOT.
X
X\section {Specifying the View Surface}
X
XThe first thing that a graphics program must do is to tell PLPLOT which
Xdevice it is going to use, and how this device is to be divided up for
Xgraph plotting. There are two routines that do this, \rou{plstar}, which
Xprompts at the console for the output device type and \rou{plbeg}, which
Xexpects to be supplied the code number of the device as an argument. The
Xcode numbers required by {\tt plbeg} are the same as displayed by {\tt
Xplstar} when it prompts for a device.
X
XBesides selecting the device, {\tt plstar} and {\tt plbeg} allow the
Xuser to divide the output device plotting area into several subpages of
Xequal size, each of which can be used separately. The routine {\tt
Xpladv} is used to advance to a particular subpage or to the next
Xsubpage. The screen is cleared or a new piece of paper is loaded, if a
Xnew subpage is requested when there are no subpages left on the current
Xpage. When a page is divided into subpages, the default character,
Xsymbol and tick sizes are scaled inversely as the square root of the
Xnumber of subpages in the vertical direction.
X
XAt the end of a plotting program, it is important to close the plotting
Xdevice by calling \rou{plend}. This flushes any
Xinternal buffers and frees any memory that may have been allocated.
XNote that if {\tt plstar}
Xor {\tt plbeg} is called more than once during a program to
Xchange the output device, an automatic call to {\tt plend} is made
Xbefore the new device is opened.
X
X\section {Defining the Viewport} \label{viewport}
X
XAfter defining the view surface, it is necessary to define the portion
Xof this surface which is to be used for plotting the graph. All lines
Xand symbols (except for labels drawn by {\tt plbox}, {\tt plmtex} and
X{\tt pllab}) are clipped at the viewport boundaries.
X
XViewports are created within the current subpage. If the division of the
Xoutput device into equally sized subpages is inappropriate, it is best
Xto specify only a single subpage which occupies the entire output device
X(by setting {\tt nx=1} and {\tt ny=1} in {\tt plbeg} or {\tt plstar}),
Xand use one of the viewport specification subroutines below to place the
Xplot in the desired position on the page.
X
XThere are two methods for specifying the viewport size, using the
Xsubroutines \rou{plvpor} and \rou{plsvpa}. Each of these has the format:
X\begin{verbatim}
Xplvpor(xmin,xmax,ymin,ymax);
Xplsvpa(xmin,xmax,ymin,ymax);
X\end{verbatim}
Xwhere in the case of {\tt plvpor}, the arguments are given in {\em
Xnormalized subpage coordinates} which are defined to run from 0.0 to 1.0
Xalong each edge of the subpage. Thus for example,
X\begin{verbatim}
Xplvpor(0.0,0.5,0.5,1.0);
X\end{verbatim}
Xuses the top left quarter of the current subpage.
X
XIn order to get a graph of known physical size, the routine {\tt plsvpa}
Xdefines the viewport in terms of absolute
Xcoordinates (millimetres) measured from the bottom left-hand corner of
Xthe current subpage. This routine should only be used when the size of
Xthe view surface is known, and a definite scaling is required.
X
XTo help the user call {\tt plsvpa} correctly, the routine \rou{plgspa}
Xis provided which returns the positions of the extremities of the
Xcurrent subpage measured in millimetres from the bottom left-hand corner
Xof the device. Thus, if to set up a viewport with a 10.0~mm margin
Xaround it within the current subpage, the following sequence of calls
Xmay be used
X\begin{verbatim}
Xplgspa(xmin,xmax,ymin,ymax);
Xplsvpa(10.0,xmax-xmin-10.0,10.0,ymax-ymin-10.0);
X\end{verbatim}
XA further routine \rou{plvsta} is available which sets up a standard
Xviewport within the current subpage with suitable margins on each side
Xof the viewport. This may be used for simple graphs, as it leaves enough
Xroom for axis labels and a title. This standard viewport is that used by
X{\tt plenv} (see Section \ref{plenv-sec}).
X
X\section {Defining the Window} \label{window}
X
XThe window must be defined after the viewport in order to map the world
Xcoordinate rectangle into the viewport rectangle. The routine
X\rou{plwind} is used to specify the rectangle in world-coordinate space.
XFor example, if we wish to plot a graph showing the collector current
X$I_C$ as a function of the collector to emitter voltage $V_{CE}$ for a
Xtransistor where $0\le I_C\le 10.0\mbox{\,mA}$ and $0\le V_{CE}\le
X12.0\mbox{\,V}$, we would call the function {\tt plwind} as follows:
X\begin{verbatim}
Xplwind(0.0,12.0,0.0,10.0);
X\end{verbatim}
XNote that each of the arguments is a floating point number, and so the
Xdecimal points are required. If the order of either the X~limits or
XY~limits is reversed, the corresponding axis will point in the opposite
Xsense, (i.e., right to left for X and top to bottom for Y). The window
Xmust be defined before any calls to the routines which actually draw the
Xdata points. Note however that {\tt plwind} may also be called to change
Xthe window at any time. This will affect the appearance of objects drawn
Xlater in the program, and is useful for drawing two or more graphs with
Xdifferent axes on the same piece of paper.
X
X\section {Annotating the Viewport}
X
XThe routine \rou{plbox} is used to specify whether a frame is drawn around
Xthe viewport and to control the positions of the axis subdivisions and
Xnumeric labels. For our simple graph of the transistor characteristics,
Xwe may wish to draw a frame consisting of lines on all four sides of the
Xviewport, and to place numeric labels along the bottom and left hand side.
XWe can also tell PLPLOT to choose a suitable tick interval and
Xthe number of subticks between the major divisions based upon the
Xdata range specified to {\tt plwind}. This is done using the following
Xstatement
X\begin{verbatim}
Xplbox("bcnst",0.0,0,"bcnstv",0.0,0);
X\end{verbatim}
XAnother routine \rou{pllab} provides for text labels for the bottom,
Xleft hand side and top of the viewport. These labels are not clipped,
Xeven though they lie outside the viewport (but they are clipped at the
Xsubpage boundaries). {\tt pllab} actually calls the more general routine
X{\tt plmtex} which can be used for plotting labels at any point relative
Xto the viewport. For our example, we may use
X\begin{verbatim}
Xpllab("V#dCE#u (Volts)","I#dC#u (mA)","TRANSISTOR CHARACTERISTICS");
X\end{verbatim}
XNote that \verb+#d+ and \verb+#u+ are escape sequences (see page
X\pageref{escape}) which allow
Xsubscripts and superscripts to be used in text.
XThey are described more
Xfully later in this chapter.
X
XThe heights of characters used for the axis and graph labels can be
Xchanged by means of the routine \rou{plschr}.
X
X\section {The Routine {\tt plenv}}\label{plenv-sec}
X
XHaving to call {\tt pladv}, {\tt plvpor}, {\tt plwind} and {\tt plbox}
Xis excessively cumbersome for drawing simple graphs. Subroutine {\tt plenv}
Xcombines all four of these in one subroutine, using the
Xstandard viewport, and a limited subset of the capabilities of {\tt plbox}.
XFor example, the graph described above could be initiated by the call:
X\begin{verbatim}
Xplenv(0.0,12.0,0.0,10.0,0,0);
X\end{verbatim}
Xwhich is equivalent to the following series of calls:
X\begin{verbatim}
Xpladv(0);
Xplvsta();
Xplwind(0.0,12.0,0.0,10.0);
Xplbox("bcnst",0.0,0,"bcnstv",0.0,0);
X\end{verbatim}
X
X\section {Setting Line Attributes}
X
XThe graph drawing routines may be freely mixed with those described in
Xthis section which allow the user to control line color, width and styles.
XThe attributes set up by these routines apply modally, i.e, all subsequent
Xobjects (lines, characters and symbols) plotted until the next change in
Xattributes are affected in the same way. The only exception to this rule
Xis that characters and symbols are not affected by a change in the line
Xstyle, but are always drawn using a continuous line.
X
XLine color \label{color} is set using the routine \rou{plcol}. The
Xargument is ignored for devices which can only plot in one color but some
Xterminals support line erasure by plotting in color zero.
X
XLine width \label{width} is set using \rou{plwid}. This option is not
Xsupported by all devices.
X
XLine style \label{style} is set using the routine \rou{plstyl}
Xor \rou{pllsty}. A broken
Xline is specified in terms of a repeated pattern consisting of marks
X(pen down) and spaces (pen up). The arguments to this routine are
Xthe number of elements in the line, followed by two pointers to
Xinteger arrays specifying
Xthe mark and space lengths in micrometers. Thus a line consisting of
Xlong and short dashes of lengths 4\,mm and 2\,mm, separated by spaces of
Xlength 1.5\,mm is specified by:
X\begin{verbatim}
Xmark[0]=4000;
Xmark[1]=2000;
Xspace[0]=1500;
Xspace[1]=1500;
Xplstyl(2,mark,space);
X\end{verbatim}
XTo return to a continuous line, just call {\tt plstyl} with first argument
Xset to zero. You can use {\tt pllsty} to chose between 8 different
Xpredefined styles.
X
X\section {Setting the Area Fill Pattern}
XThe routine \rou{plpat} can be used to set the area fill pattern. The
Xpattern consists of 1 or 2 sets of parallel lines with specified
Xinclinations and spacings. The arguments to this routine are the
Xnumber of sets to use (1 or 2) followed by two pointers to integer
Xarrays (of 1 or 2 elements) specifying the inclinations in tenths
Xof a degree and the spacing in micrometers. (The inclination should
Xbe between -900 and 900.) Thus to specify an area fill pattern consisting
Xof horizontal lines spaced 2\,mm apart use:
X\begin{verbatim}
X*inc=0;
X*del=2000;
Xplpat(1,inc,del);
X\end{verbatim}
XTo set up a symmetrical crosshatch pattern with lines directed 30 degrees
Xabove and below the horizontal and spaced 1.5\,mm apart use:
X\begin{verbatim}
X*inc=300;
X*(inc+1)=-300;
X*del=1500;
X*(del+1)=1500;
Xplpat(2,inc,del);
X\end{verbatim}
X
XThe routine \rou{plpsty} can be used to select from 1 of 8 predefined
Xpatterns.
X
XThe area fill routines also use the current line style, width and
Xcolors to give a virtually infinite number of different patterns!
X
X\section {Setting Character and Symbol Attributes}
X
XThere are two character sets included with PLPLOT. These are known as
Xthe standard and extended character sets respectively. The standard
Xcharacter set is a subset of the extended set. It contains 177
Xcharacters including the ascii characters in a normal style font,
Xthe greek alphabet and several plotter symbols. The extended character
Xset contains almost 2000 characters, including four font styles,
Xand several math, musical and plotter symbols.
X
XThe standard character set is loaded into memory automatically when
X{\tt plstar} or {\tt plbeg} is called. The extended character set
Xis loaded by calling \rou{plfontld}. (The extended character set eats
Xup about 50 kbytes of memory whereas the standard set takes
Xup about 5 kbytes.) {\tt plfontld} can be used to switch between the
Xextended and standard sets. (One set is unloaded before the next is
Xloaded.)
X
XWhen the extended character set is loaded there are four different
Xfont styles to choose from. In this case,
Xthe routine \rou{plfont} sets up the default font for all character
Xstrings. It may be over-ridden for (a portion) of a string by using an
Xescape sequence within the text, as described below.
XThe default font (1) is simple and fastest to draw,
Xthe others are useful for presentation plots on a high-resolution
Xdevice.
X
XThe font codes are interpreted as follows:
X\begin{itemize}
X   \item{\tt font = 1}: normal simple font
X   \item{\tt font = 2}: roman font
X   \item{\tt font = 3}: italic font
X   \item{\tt font = 4}: script font
X\end{itemize}
X
XThe routine \rou{plschr} is used to set up the size of subsequent
Xcharacters drawn. The actual height of a character is the product of the
Xdefault character size and a scaling factor. If no call is made to
X{\tt plschr}, the default character size is set up depending on the number
Xof subpages defined in the call to {\tt plstar} or {\tt plbeg}, and the
Xscale is set to
X1.0. Under normal circumstances, it is recommended that the user does not
Xalter the default height, but simply use the scale parameter. This can
Xbe done by calling {\tt plschr} with {\tt def=0.0} and {\tt scale} set to the
Xdesired multiple of the default height. If the default height is to be
Xchanged, {\tt def} is set to the new default height in millimetres, and
Xthe new character height is again set to {\tt def} multiplied by {\tt
Xscale}.
X
XThe routine \rou{plssym} sets up the size of all subsequent symbols
Xdrawn by calls to {\tt plpoin} and {\tt plsym}. It operates analogously
Xto {\tt plschr} as described above.
X
XThe lengths of major and minor ticks on the axes are set up by the routines
X\rou{plsmaj} and \rou{plsmin}.
X
X\section {Escape Sequences in Text} \label{escape}
X
XThe routines which draw text all allow you to include escape
Xsequences in the text to be plotted. These are character sequences
Xwhich are are interpreted as instructions to
Xchange fonts, draw superscripts and subscripts, draw non-ASCII
X(e.g., Greek letters) etc. All escape sequences start with a number
Xsymbol (\verb+#+).
X
XThe following escape sequences are defined:
X\begin{itemize}
X   \item \verb+#u+: move up to the superscript position
X    (ended with \verb+#d+)
X   \item \verb+#d+: move down to subscript position
X    (ended with \verb+#u+)
X   \item \verb+#b+: backspace (to allow overprinting)
X   \item \verb+##+: number symbol
X   \item \verb.#+.: toggle overline mode
X   \item \verb.#-.: toggle underline mode
X   \item \verb+#gx+: Greek letter corresponding to Roman letter {\tt x}
X                     (see below)
X   \item \verb+#fn+: switch to normal font
X   \item \verb+#fr+: switch to Roman font
X   \item \verb+#fi+: switch to italic font
X   \item \verb+#fs+: switch to script font
X   \item \verb+#(nnn)+: Hershey character nnn (1 to 4 decimal digits)
X\end{itemize}
X
XSections of text can have an underline or overline appended. For example,
Xthe string
X\[
X{\rm\overline{S}(\underline{freq})}
X\]
Xis obtained by specifying \verb."#+S#+(#-freq#-)"..
X
XGreek letters are obtained by \verb+#g+ followed by a Roman letter.
XTable~\ref{greek} shows how these letters map into Greek characters.
X\begin{table}
X   \centering
X   \begin{tabular}{|l|*{12}{c|}}
X   \hline
X   Roman&A&B&G&D&E&Z&Y&H&I&K&L&M\\
X   \hline
X   Greek&A & B & $\Gamma$ & $\Delta$ & E & Z & H & $\Theta$ & I & K &
X   $\Lambda$ & M \\
X   \hline\hline
X   Roman&N&C&O&P&R&S&T&U&F&X&Q&W\\
X   \hline
X   Greek&N & $\Xi$ & O & $\Pi$ & P & $\Sigma$ &
X   T & $\Upsilon$ & $\Phi$ & X & $\Psi$ & $\Omega$ \\
X   \hline\hline
X   Roman&a&b&g&d&e&z&y&h&i&k&l&m\\
X   \hline
X   Greek&   $\alpha$ & $\beta$ & $\gamma$ & $\delta$ & $\epsilon$ & $\zeta$ &
X   $\eta$ & $\theta$ & $\iota$ & $\kappa$ &
X   $\lambda$ & $\mu$ \\
X   \hline\hline
X   Roman&n&c&o&p&r&s&t&u&f&x&q&w\\
X   \hline
X   Greek& $\nu$ & $\xi$ & o & $\pi$ & $\rho$ & $\sigma$ &
X   $\tau$ & $\upsilon$ & $\phi$ & $\chi$ & $\psi$ & $\omega$ \\
X   \hline
X   \end{tabular}
X\caption{Roman characters corresponding to Greek characters}
X\label{greek}
X\end{table}
X
X\section {Three Dimensional Surface Plots} \label{threed}
X
XPLPLOT includes routines that will represent a single-valued function
Xof two variables as a surface. In this section, we shall assume that
Xthe function to be plotted is {\tt Z[X][Y]}, where {\tt Z} represents
Xthe dependent variable and {\tt X} and {\tt Y} represent the independent
Xvariables.
X
XAs usual, we would like to refer to a three dimensional point {\tt (X,Y,Z)}
Xin terms of some meaningful user-specified coordinate system. These are
Xcalled {\em three-dimensional world coordinates}. We need to specify the
Xranges of these coordinates, so that the entire surface is contained within the
Xcuboid defined by ${\tt xmin}<{\tt x}<{\tt xmax}$,
X${\tt ymin}<{\tt y}<{\tt ymax}$ and
X${\tt zmin}<{\tt z}<{\tt zmax}$. Typically, we shall want to view the
Xsurface from a variety of angles, and to facilitate this, a two-stage
Xmapping of the enclosing cuboid is performed. Firstly, it is mapped
Xinto another cuboid called the {\em normalized box} whose size must also
Xbe specified by the user, and secondly this normalized box is viewed from
Xa particular azimuth and elevation so that it can be projected onto the
Xtwo-dimensional window.
X
XThis two-stage transformation process allows considerable flexibility in
Xspecifying how the surface is depicted. The lengths of the sides of the
Xnormalized box are independent of the world coordinate ranges of each of the
Xvariables, making it possible to use ``reasonable'' viewing angles even if the
Xranges of the world coordinates on the axes are very different. The size of the
Xnormalized box is determined essentially by the size of the two-dimensional
Xwindow into which it is to be mapped. The normalized box is centred about the
Xorigin in the $x$ and $y$ directions, but rests on the plane ${\tt z=0}$. It is
Xviewed by an observer located at altitude {\tt alt} and azimuth {\tt az}, where
Xboth angles are measured in degrees. The altitude should be restricted to the
Xrange zero to ninety degrees for proper operation, and represents the viewing
Xangle above the xy plane. The azimuth is defined so that when {\tt az=0}, the
Xobserver sees the xz plane face on, and as the angle is increased, the observer
Xmoves clockwise around the box as viewed from above the xy plane. The azimuth
Xcan take on any value.
X
XThe first step in drawing a surface plot is to decide on the size of the
Xtwo-dimensional window and the normalized box. For example, we could choose
Xthe normalized box to have sides of length
X\begin{verbatim}
Xbasex=2.0;
Xbasey=4.0;
Xheight=3.0;
X\end{verbatim}
XA reasonable range for the $x$ coordinate of the two-dimensional
Xwindow is -2.5 to +2.5, since the length of the diagonal across the base of
Xthe normalized box is $\sqrt{2^2+4^2} = 2\sqrt{5}$, which fits into this
Xcoordinate range. A reasonable range for the $y$ coordinate of the two
Xdimensional window in this case is -2.5 to +4, as the the projection of the
Xnormalized box lies in this range for the allowed range of viewing angles.
X
XThe routine \rou{plwind} or \rou{plenv} is used in the usual way
Xto establish the size of the two-dimensional window. The routine
X\rou{plw3d} must then be called to establish the range of the three
Xdimensional world coordinates, the size of the normalized box and the
Xviewing angles. After calling {\tt plw3d}, the actual surface is
Xdrawn by a call to \rou{plot3d}.
X
XFor example, if the three-dimensional world-coordinate ranges are
X$-10.0\le{\tt x}\le 10.0$, $-3.0\le{\tt y}\le +7.0$ and
X$0.0\le{\tt z}\le 8.0$, we could use the following statements:
X\begin{verbatim}
X      xmin2d = -2.5;
X      xmax2d =  2.5;
X      ymin2d = -2.5;
X      ymax2d =  4.0;
X      plenv(xmin2d,xmax2d,ymin2d,ymax2d);
X      basex = 2.0;
X      basey = 4.0;
X      height = 3.0;
X      xmin = -10.0;
X      xmax = 10.0;
X      ymin = -3.0;
X      ymax = 7.0;
X      zmin = 0.0;
X      zmax = 8.0;
X      alt = 45.0;
X      az = 30.0;
X      side = 1;
X      plw3d(basex,basey,height,xmin,xmax,ymin,ymax,zmin,zmax,alt,az);
X      plot3d(x,y,z,ly,nx,ny,opt,side);
X\end{verbatim}
X
XThe values of the function are stored in a two-dimensional
Xarray {\tt z[][ly]} where the array element {\tt z[i][j]} contains the value
Xof the function at the point $x_i$, $y_j$. Note that the values of
Xthe independent variables $x_i$ and $y_j$ do not need to be equally spaced,
Xbut they must lie on a rectangular grid. Thus two further arrays {\tt x[nx]}
Xand {\tt y[ny]} are required as arguments to {\tt plot3d} to specify the
Xvalues of the independent variables. The values in the arrays x and y must
Xbe strictly increasing with the index. The argument {\tt opt} specifies
Xhow the surface is outlined. If {\tt opt=1}, a line is drawn representing
Xz as a function of x for each value of y, if {\tt opt=2}, a line is drawn
Xrepresenting z as a function of y for each value of x, and if {\tt opt=3},
Xa net of lines is drawn. The first two options may be preferable if one of
Xthe independent variables is to be regarded as a parameter, whilst the third
Xis better for getting an overall picture of the surface. If side is equal to
Xone then sides are drawn on the figure so that the graph doesn't appear to
Xfloat.
X
XThe routine \rou{plmesh} is similar to {\tt plot3d,} except that it is
Xused for drawing mesh plots. Mesh plots allow you to see both the top and
Xbottom sides of a surface mesh, while 3D plots allow you to see the top
Xside only (like looking at a solid object). The side option is not
Xavailable with {\tt plmesh.}
X
XLabelling a three-dimensional or mesh plot is somewhat more complicated
Xthan a two
Xdimensional plot due to the need for skewing the characters in the label
Xso that they are parallel to the coordinate axes. The routine \rou{plbox3}
Xthus combines the functions of box drawing and labelling. Its parameters
Xare described more fully in Chapter \ref{reference}.
X
X\section {Contour Plots}\label{contour}
X
XA routine is available in PLPLOT which performs a contour plot of data
Xstored in a two-dimensional array. A contour following algorithm is
Xused, so that it is possible to use non-continuous line styles.
X
XThe routine \rou{plcont} has the form
X\name{plcont(z,nx,ny,kx,lx,ky,ly,clevel,nlevel,pltr)}
Xwhere {\tt z} is the two-dimensional array of size ${\tt nx}\times{\tt ny}$
Xcontaining samples of the function to be contoured. The parameters
X{\tt kx}, {\tt lx}, {\tt ky} and {\tt ly} specify the portion of {\tt z}
Xthat is to be considered. The array {\tt clevel} of length {\tt nlevel}
Xis a list of the desired contour levels.
X
XThe path of each contour is initially computed in terms of the values of the
Xarray indicies which range from {\tt 0} to {\tt nx-1} in the
Xfirst index and from
X{\tt 0} to {\tt ny-1} in the second index.
XBefore these can be drawn in the current
Xwindow (see page \pageref{window} in Section \ref{window}), it is
Xnecessary to
Xconvert from these array indicies into world coordinates. This is done by
Xpassing a pointer to a user-defined function to {\tt plcont}.  This
Xfunction pointer is the last argument {\tt pltr}.
XThis function must be declared as type {\tt void} in the
Xmodule which calls {\tt plcont}. This transformation function
Xmust have the parameter list
X\name{void pltr(x,y,tx,ty);}
Xwhere {\tt (x,y)}
Xis the point through which the contour runs expressed in
Xterms of array indicies, and {\tt (tx,ty)} are pointers to float variables
Xwhich are the world coordinates of
Xthe point which corresponds to these indicies.
X
XOften, the transformation between array indices and world coordinates can
Xbe expressed as a linear transformation. A routine is provided within the
Xlibrary which can be passed to {\tt plcont} as {\tt pltr}. This
Xtransformation routine is
X\begin{verbatim}
X
X#include "plplot.h"
X
Xvoid xform(x,y,tx,ty)
Xfloat x, y, *tx, *ty;
X{
X      extern float tr[];
X
X      *tx = tr[0]*x + tr[1]*y + tr[2];
X      *ty = tr[3]*x + tr[4]*y + tr[5];
X}
X\end{verbatim}
XThus by setting up the values in the array {\tt tr[]}, we can
Xapply an arbitrary translation, rotation and/or shear to the array before
Xdrawing out the contours. By defining other transformation subroutines,
Xit is possible to draw contours wrapped around polar grids etc.
X
XAs an example in setting up {\tt tr[]}, suppose that the array {\tt z}
Xis of size $21 \times 41$ and contains the values of the function
X$z[x][y]$,
Xwhere $x$ ranges from 0.0 to 4.0 and $y$ ranges from -8.0 to 8.0.
XFurthermore,
Xlet us also suppose that the window (as defined using {\tt plenv} or
X{\tt plwind}) covers this range of world coordinates.
XSince we wish the index
X(0,0) in array {\tt z} to map to (0.0,-8.0) and the index (20,40) to map
Xto (4.0,8.0), and for there to be no skew in the axes, we should choose
Xelements of {\tt tr[]} so that
X\[
X   \begin{array}{l@{\;=\;}l}
X   tx & 0.2x \\
X   ty & 0.4y - 8.
X   \end{array}
X\]
Xand so {\tt tr[0]=0.2}, {\tt tr[1]=0.0}, {\tt tr[2]=0.0},
X{\tt tr[3]=0.0}, {\tt tr[4]=0.4}, {\tt tr[5]=-8.}.
X
END_OF_FILE
if test 24805 -ne `wc -c <'docs/chapter3.tex'`; then
    echo shar: \"'docs/chapter3.tex'\" unpacked with wrong size!
fi
# end of 'docs/chapter3.tex'
fi
echo shar: End of archive 8 \(of 12\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
	amiga@cs.odu.edu	
or	amiga@xanth.cs.odu.edu	( obsolescent mailers may need this address )
or	...!uunet!xanth!amiga	( very obsolescent mailers need this address )

Comments, questions, and suggestions s should be addressed to ``amiga-request''
(only use ``amiga'' for submissions) at the above addresses.