home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / graphfor.zip / GRAPHLIB.FOR < prev    next >
Text File  |  1990-05-03  |  42KB  |  1,077 lines

  1. ****************************************************************************
  2. c
  3. c      SHAREWARE NOTICE              Copyright (C) D.I. Hoyer, 1990.
  4. c     ==================             GRAPHLIB.for  v2.0
  5. c
  6. c     Please register by sending US$30-00 or Aus$40-00 to the address below
  7. c     if you find these Fortran subroutines useful. Registered users will
  8. c     receive the latest version, plus technical support on queries related
  9. c     to these routines.
  10. c
  11. c                    David I Hoyer
  12. c                    31 Rossian Place
  13. c                    Cherrybrook  NSW 2120
  14. c                    AUSTRALIA
  15. c
  16. c     This subroutine library is a shareware product. Copies of the original
  17. c     unmodified programs and manual on disk may be made and distributed as 
  18. c     required, as long as they are not charged for. You may not modify the 
  19. c     source code or manual except for your personal use. 
  20. c
  21. c     Requirements  :  ANSI Fortran 77, full language.
  22. c
  23. ****************************************************************************
  24. c
  25. c     No responsibility is accepted for any errors in this software, 
  26. c     or for any loss or damage resulting from using it.
  27. c
  28. ****************************************************************************
  29.  
  30.       SUBROUTINE PRTGRF(IOFF,MMAXX,MMAXY,LOHI,IGRAPH)
  31. *
  32. * Print graph IGRAPH on the dot matrix printer.
  33. *
  34. * Set the following character constants after referring to the printer manual:
  35. *
  36. * LSP7 and LSP12 = Set line spacing to 7/72" and 12/72" (1/6") respectively.
  37. * LSP1  = Set line spacing to 1/216"  [or  1/144"]   (for hi-res plotting)
  38. * LSP20 = Set line spacing to 20/216" [or 13/144"]   ( "    "       "    )
  39. * GFXON = Set graphics mode on, with number of dot columns across page
  40. *             Epson, Star NX-10 : <ESC> 'K'...  =  60 dpi (lo-res)
  41. *                                 <ESC> 'L'...  = 120 dpi (hi-res)
  42. *
  43. * LOHI : Two options are available, viz low and high density.
  44. * 1= Low density = 72 dots per inch vertical and 60 horizontal. Each
  45. *                  row of integers is printed as two lines of 7 rows
  46. *                  each on the printer. 8"x10" = 41k. IGRAPH(480,43)
  47. * 2= High   "    = 144 dpi vert and 120 horiz. This is printed in two
  48. *                  interleaved rows, with 1/216" or 1/144" line feed.
  49. *                  8"x10" requires about 164 kbytes : IGRAPH(960,86)
  50. *
  51. * BUT NOTE: Some printers have a basic vertical line spacing of 60 & 180 dpi
  52. * --------  rather than the 72 discussed above. This is indicated if the
  53. *    printer manual refers to vertical line settings as n/60 or n/180 dpi
  54. *    instead of n/72 or n/216. If this is the case, try the following:
  55. *    LSP7  - set line spacing to 7/60"
  56. *    LSP1  - set line spacing to 1/180"
  57. *    LSP20 - set line spacing to 20/180"
  58. * Then go to SUBROUTINE PREP(... and set
  59. *    DPIV = 60.   (for 60 dots per inch vertical)
  60. *
  61. * If the printer cannot do line feeds of 1/216" to 1/144" then only lo-res
  62. * graphs can be printed.
  63. *
  64. *
  65.       INTEGER*2 IGRAPH
  66.       CHARACTER*5 LSP12
  67.       CHARACTER*4 GFXON
  68.       CHARACTER*3 LSP1,LSP20
  69.       CHARACTER*2 LSP7
  70.       CHARACTER BLANK*100,LINE1*1200,LINE2*1200
  71.       DIMENSION IGRAPH(MMAXX,MMAXY)
  72.       DATA BLANK/'
  73.      $                                              '/
  74. *
  75. * This subroutine is set up for IBM, Epson, Star type dot matrix printers
  76. * which have a smallest line feed of 1/216". Some printers have a smallest
  77. * line feed of 1/144", in which case you should re-define LSP20 to :
  78. *      LSP20 = CHAR(27)//'3'//CHAR(13)
  79. *
  80. * If you have a printer which uses different graphics commands, or if the
  81. * graph is not printing out correctly, consult the printer manual and change
  82. * the appropriate parameters for LSP7, LSP12, LSP1, LSP20, GFXON :
  83. *
  84.       LSP7 = CHAR(27)//'1'
  85.       LSP12 = CHAR(27)//'A'//CHAR(12)//CHAR(27)//'2'
  86.       LSP1 = CHAR(27)//'3'//CHAR(1)
  87.       LSP20 = CHAR(27)//'3'//CHAR(20)
  88. *
  89.       IOFF = MAX(1,IOFF)
  90.       I2 = MMAXX/256
  91.       I1 = MMAXX - 256*I2
  92.       IF(LOHI.EQ.1) THEN  ! Set 60 dots per inch across the page (lo-res)
  93.         GFXON = CHAR(27)//'K'//CHAR(I1)//CHAR(I2)
  94.       ELSE  ! Set 120 dots per inch across the page (hi-res)
  95.         GFXON = CHAR(27)//'L'//CHAR(I1)//CHAR(I2)
  96.       ENDIF
  97.       WRITE(6,303) LSP7
  98.  303  FORMAT(1X,A5)
  99.       DO 10 IROW=MMAXY, 1, -1
  100.         DO 30 ICOL=1, MMAXX
  101.           ICH1 = IGRAPH(ICOL,IROW)/128
  102.           ICH2 = 2*(IGRAPH(ICOL,IROW) - 128*ICH1)
  103.           ICH1 = 2*ICH1
  104.           IF(ICH1.EQ.26) ICH1=18
  105.           IF(ICH2.EQ.26) ICH2=18
  106.           LINE1(ICOL:ICOL) = CHAR(ICH1)
  107.           LINE2(ICOL:ICOL) = CHAR(ICH2)
  108.   30    CONTINUE
  109.         IF(LOHI.EQ.1) THEN
  110.           WRITE(6,101) BLANK(1:IOFF),GFXON,LINE1(1:MMAXX),BLANK(1:IOFF),
  111.      $     GFXON,LINE2(1:MMAXX)
  112.  101      FORMAT(1X,A,A5,A/1X,A,A5,A)
  113.         ELSE
  114.           WRITE(6,404) BLANK(1:IOFF),GFXON,LINE1(1:MMAXX),LSP1
  115.           WRITE(6,404) BLANK(1:IOFF),GFXON,LINE2(1:MMAXX),LSP20
  116.  404      FORMAT(1X,A,A5,A,A3)
  117.         ENDIF 
  118.   10  CONTINUE
  119.       WRITE(6,303) LSP12   ! return the printer to 1/6" spacing
  120.       RETURN
  121.       END
  122.  
  123. *-----------------------------------------------------------------------
  124.  
  125.       SUBROUTINE SETBIT(I,J)
  126. *
  127. * Set bit j in integer i. This method is marginally faster than using
  128. * the IOR function which is available with some Fortran compilers.
  129. *
  130.       INTEGER*2 I
  131.       DIMENSION MASK(0:14)
  132.       DATA MASK/16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1/
  133.       IF(MOD(I,MASK(J-1)).LT.MASK(J)) I = I + MASK(J)
  134.       RETURN
  135.       END
  136.  
  137. *-----------------------------------------------------------------------
  138.  
  139.       SUBROUTINE PREP(XL,YL,NDIVX,NDIVY,XMINA,XMAXA,YMINA,YMAXA,
  140.      $ XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IVH)
  141. *
  142. * Prepare the input data for plotting.
  143. * Calc graph sizes and limits, log conversions etc.
  144. * This subroutine must be called before any plotting is done.
  145. *
  146. * DPIH : Horizontal dots per inch for lo-res plotting (normally 60)
  147. * DPIV : Vertical dots per inch for lo-res plotting (normally 72 or 60)
  148. *
  149.       DPIH = 60.
  150.       DPIV = 72.
  151. *
  152. * If log scales are specified, then take logs of axis details
  153.       IF(NDIVX.EQ.0) THEN
  154.         XMIN = ALOG10(XMIN)
  155.         XMAX = ALOG10(XMAX)
  156.       ENDIF
  157.       IF(NDIVY.EQ.0) THEN
  158.         YMIN = ALOG10(YMIN)
  159.         YMAX = ALOG10(YMAX)
  160.       ENDIF
  161. * Allow extra space above, below, left & right, for labels and headings.
  162. * The numbers refers to cm here.
  163.       XMINA = XMIN - 1./XL*(XMAX-XMIN)
  164.       XMAXA = XMAX + 1./XL*(XMAX-XMIN)
  165.       YMINA = YMIN - 1./YL*(YMAX-YMIN)
  166.       YMAXA = YMAX + 1./YL*(YMAX-YMIN)
  167.       XL = XL + 2.
  168.       YL = YL + 2.
  169.       IF(IVH.EQ.1) THEN
  170. *------ Vertical format (portrait, or normal)
  171.         WIDTH = XL
  172.         HEIGHT = YL
  173.       ELSE
  174. *------ If horizontal (landscape) format selected, transform width/height
  175.         WIDTH = YL
  176.         HEIGHT = XL
  177.       ENDIF
  178. * Set the number of dots vert. and horiz. for required graph size
  179.       IF(LOHI.EQ.1) THEN
  180.         MAXX = INT(WIDTH*DPIH/2.54+1.5)
  181.         MAXY = INT(HEIGHT*DPIV/2.54+1.5)
  182.       ELSE
  183.         MAXX = INT(WIDTH*2*DPIH/2.54+1.5)
  184.         MAXY = INT(HEIGHT*2*DPIV/2.54+1.5)
  185.       ENDIF
  186.       MMAXX = MAXX
  187.       MMAXY = MAXY/14+1
  188.       IF(IVH.EQ.2) THEN
  189.         I = MAXX
  190.         MAXX = MAXY
  191.         MAXY = I
  192.       ENDIF
  193.       RETURN
  194.       END
  195.  
  196. *-----------------------------------------------------------------------
  197.  
  198.       SUBROUTINE CLRBOX(X1,Y1,X2,Y2,LTYP,XMINA,XMAXA,YMINA,YMAXA,
  199.      $ XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  200. *
  201. * Clear a rectangular area of the screen, and draw a box around
  202. * the cleared area as an additional option.
  203. *
  204. * NOTE: This sub-program contains the IAND(-,-) statement which is not
  205. *       standard Fortran-77. However, most F77 compilers recognise it.
  206. *       If yours does not recognise it you will have to delete this
  207. *       subroutine, and the reference to it in the main program.
  208. *
  209. * (X1,Y1) = coordinates of top left corner of box to be cleared
  210. * (X2,Y2) = coordinates of bottom right corner of box to be cleared
  211. * LTYP    = Line type for border around box (0=none, 1=solid etc.)
  212. *
  213. * Useful for clearing an area which may contain grid lines, or
  214. * other data, before drawing a legend table or other text.
  215. *
  216.  
  217.       INTEGER*2 IGRAPH
  218.       DIMENSION IGRAPH(MMAXX,MMAXY), MASK1(14), MASK2(14)
  219.       DIMENSION MASKH1(14), MASKH2(14)
  220.       DATA MASK2/16382,16380,16376,16368,16352,16320,16256,16128,
  221.      $           15872,15360,14336,12288,8192,0/
  222.       DATA MASK1/1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383/
  223.       DATA MASKH2/16382,16254,16252,15996,15992,15480,15472,14448,
  224.      $            14432,12384,12352,8256,8192,0/
  225.       DATA MASKH1/1,129,131,387,391,903,911,1935,1951,3999,4031,
  226.      $            8127,8191,16383/
  227.  
  228. * First calc integer values of the box coordinates.
  229.       IF(IVH.EQ.1) THEN
  230.         IX1 = INT((X1-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+1.5)
  231.         IY1 = INT((Y1-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  232.         IX2 = INT((X2-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+1.5)
  233.         IY2 = INT((Y2-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  234.       ELSE
  235.         IX1 = MAXY - INT((Y1-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  236.         IY1 = INT((X1-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+0.5)
  237.         IX2 = MAXY - INT((Y2-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  238.         IY2 = INT((X2-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+0.5)
  239.       ENDIF
  240. * Sort ix1, ix2 into order, and sort iy1, iy2 into order
  241.       IF(IX2<IX1) THEN
  242.         I = IX1
  243.         IX1 = IX2
  244.         IX2 = I
  245.       ENDIF
  246.       IF(IY2<IY1) THEN
  247.         I = IY1
  248.         IY1 = IY2
  249.         IY2 = I
  250.       ENDIF
  251. * Prepare for clearing
  252.       JY2 = IY2/14
  253.       JY1 = (IY1-2)/14+2
  254.       JJY2 = IY2 - 14*JY2
  255.       JJY1 = IY1 - 14*(JY1-2)
  256. * For ix1 to ix2 clear whole integers jy1 to jy2
  257.       IF(JY1.LE.JY2) THEN
  258.         DO 10 I=IX1,IX2
  259.           DO 20 J=JY1,JY2
  260.             IGRAPH(I,J) = 0
  261.   20      CONTINUE
  262.   10    CONTINUE
  263.       ENDIF
  264. * For ix1 to ix2 clear partial integer jy2+1
  265.       IF(JY2.LT.MAXY.AND.JJY2.GT.0.AND.JJY2.LT.15) THEN
  266.         IF(LOHI.EQ.1) J = MASK2(JJY2)
  267.         IF(LOHI.EQ.2) J = MASKH2(JJY2)
  268.         DO 30 I=IX1,IX2
  269.           IGRAPH(I,JY2+1) = IAND(IGRAPH(I,JY2+1),J)
  270.   30    CONTINUE
  271.       ENDIF
  272. * For ix1 to ix2 clear partial integer jy1-1
  273.       IF(JY1.GT.1.AND.JJY1.LT.15.AND.JJY1.GT.0) THEN
  274.         IF(LOHI.EQ.1) J = MASK1(JJY1)
  275.         IF(LOHI.EQ.2) J = MASKH1(JJY1)
  276.         DO 40 I=IX1,IX2
  277.           IGRAPH(I,JY1-1) = IAND(IGRAPH(I,JY1-1),J)
  278.   40    CONTINUE
  279.       ENDIF
  280. * Now draw the border
  281.       IF(LTYP.GT.0) THEN
  282.         CALL LINE(LTYP,X1,Y2,X2,Y2,XMINA,XMAXA,YMINA,YMAXA,XMIN,
  283.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  284.         CALL LINE(LTYP,X2,Y2,X2,Y1,XMINA,XMAXA,YMINA,YMAXA,XMIN,
  285.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  286.         CALL LINE(LTYP,X2,Y1,X1,Y1,XMINA,XMAXA,YMINA,YMAXA,XMIN,
  287.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  288.         CALL LINE(LTYP,X1,Y1,X1,Y2,XMINA,XMAXA,YMINA,YMAXA,XMIN,
  289.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  290.       ENDIF
  291.       RETURN
  292.       END
  293.  
  294. *-----------------------------------------------------------------------
  295.  
  296.       SUBROUTINE AXES(IGRID,NDIVX,NDIVY,NSDIVX,NSDIVY,NDPX,NDPY,
  297.      $ GLABEL,XLABEL,YLABEL,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,
  298.      $ MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  299. *
  300. * Draw a set of axes on linear or logarithmic scales. 
  301. * IGRID = 0 for no grid lines, 
  302. *       > 0 to draw grid lines, in line type specified by IGRID
  303. *         (eg. IGRID = 1 for solid line, 2 for dotted .....)
  304. * NDIVX, NDIVY  = No of major divisions along x- and y-axes
  305. *                (>0 for linear scale, 0 for log.)
  306. * NSDIVX,NSDIVY = No of minor (secondary) divisions per major division (x,y)
  307. * NDPX, NDPY    = No of decimal places for axis labels
  308. * GLABEL        = Graph title
  309. * XLABEL, YLABEL= x- and y-axis titles
  310. *
  311.       INTEGER*2 IGRAPH
  312.       CHARACTER*80 GLABEL, XLABEL, YLABEL, AXVAL, FMT
  313.       DIMENSION IGRAPH(MMAXX,MMAXY)
  314.       CALL LINE(1,XMIN,YMIN,XMAX,YMIN,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  315.      $ XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  316.       CALL LINE(1,XMIN,YMIN,XMIN,YMAX,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  317.      $ XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  318.       CALL LINE(1,XMIN,YMAX,XMAX,YMAX,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  319.      $ XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  320.       CALL LINE(1,XMAX,YMAX,XMAX,YMIN,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  321.      $ XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,0)
  322. * Plot graph heading 
  323.       ITXSIZ = LOHI+1
  324.       Y = YMAX + FLOAT(LOHI*15)/FLOAT(MAXY)*(YMAXA-YMINA)
  325.       X = (XMAX+XMIN)/2. - FLOAT((LENG(GLABEL)-1)*(LOHI*2-1)*3)/
  326.      $     FLOAT(MAXX)*(XMAXA-XMINA)
  327.       CALL TEXT(X,Y,1,ITXSIZ,GLABEL,XMINA,XMAXA,YMINA,YMAXA,XMINA,YMINA,
  328.      $ XMAXA,YMAXA,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  329.       DO 30 IAX=0, 1
  330. * Plot x-axis or y-axis label
  331.         IF(IAX.EQ.0) THEN
  332.           NDIVS = NDIVX
  333.           NSDIVS = NSDIVX
  334.           AXMIN = XMIN
  335.           AXMAX = XMAX
  336.           Y = YMIN - FLOAT(LOHI*18)/FLOAT(MAXY)*(YMAXA-YMINA)
  337.           X = (XMAX+XMIN)/2. - FLOAT((LENG(XLABEL)-1)*LOHI*3)/
  338.      $         FLOAT(MAXX)*(XMAXA-XMINA)
  339.           ITXSIZ = LOHI
  340.           CALL TEXT(X,Y,1,ITXSIZ,XLABEL,XMINA,XMAXA,YMINA,YMAXA,XMINA,
  341.      $     YMINA,XMAXA,YMAXA,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  342.         ELSE
  343.           NDIVS = NDIVY
  344.           NSDIVS = NSDIVY
  345.           AXMIN = YMIN
  346.           AXMAX = YMAX
  347.           X = XMIN - FLOAT(LOHI*20)/FLOAT(MAXX)*(XMAXA-XMINA)
  348.           Y = (YMAX+YMIN)/2. - FLOAT((LENG(YLABEL)-1)*LOHI*3)/
  349.      $         FLOAT(MAXY)*(YMAXA-YMINA)
  350.           ITXSIZ = LOHI
  351.           CALL TEXT(X,Y,2,ITXSIZ,YLABEL,XMINA,XMAXA,YMINA,YMAXA,XMINA,
  352.      $     YMINA,XMAXA,YMAXA,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  353.         ENDIF
  354. * Set size of tick marks along axis
  355.         IF(IAX.EQ.0) AXLL = (YMAXA-YMINA)*3./FLOAT(MAXY-1)
  356.         IF(IAX.EQ.1) AXLL = (XMAXA-XMINA)*3./FLOAT(MAXX-1)
  357.         IF(LOHI.EQ.2) AXLL = 2.*AXLL
  358. * Calc number of major/minor tick marks on axis
  359.         JDIV = NSDIVS
  360.         IF(JDIV.LT.1) JDIV = 1
  361.         IF(NDIVS.GT.0) THEN  ! Linear axis scale
  362.           I1 = 0
  363.           I2 = NDIVS
  364.         ELSE  ! Log scale
  365.           IF(JDIV.NE.1) JDIV = 9
  366.           I1 = INT(AXMIN) - 1
  367.           I2 = INT(AXMAX) + 1
  368.         ENDIF
  369. * Plot tick mark(s) on the axis
  370.         DO 10 I=I1, I2
  371.           DO 20 J = 1, JDIV
  372.             AXL = AXLL
  373.             IF(J.EQ.1) AXL = AXLL*1.5
  374.             IF(NDIVS.GT.0) THEN
  375.               XY = AXMIN+(AXMAX-AXMIN)/FLOAT(NDIVS)*(I+(J-1)/
  376.      $             FLOAT(NSDIVS))
  377.             ELSE
  378.               XY = ALOG10(10.**FLOAT(I)*FLOAT(J))
  379.             ENDIF
  380.             IF(IAX.EQ.0) THEN
  381.               CALL LINE(1,XY,YMAX,XY,YMAX-AXL,XMINA,XMAXA,YMINA,YMAXA,
  382.      $         XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,
  383.      $         IVH,NPP,0)
  384.               CALL LINE(1,XY,YMIN,XY,YMIN+AXL,XMINA,XMAXA,YMINA,YMAXA,
  385.      $         XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,
  386.      $         IVH,NPP,0)
  387.             ELSE
  388.               CALL LINE(1,XMAX,XY,XMAX-AXL,XY,XMINA,XMAXA,YMINA,YMAXA,
  389.      $         XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,
  390.      $         IVH,NPP,0)
  391.               CALL LINE(1,XMIN,XY,XMIN+AXL,XY,XMINA,XMAXA,YMINA,YMAXA,
  392.      $         XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,
  393.      $         IVH,NPP,0)
  394.             ENDIF
  395.             IF(IGRID.GT.0) THEN
  396.               NPP = 0
  397.               IF(IAX.EQ.0) CALL LINE(IGRID,XY,YMIN,XY,YMAX,XMINA,XMAXA,
  398.      $         YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,
  399.      $         LOHI,IGRAPH,IVH,NPP,0)
  400.               IF(IAX.EQ.1) CALL LINE(IGRID,XMIN,XY,XMAX,XY,XMINA,XMAXA,
  401.      $         YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,
  402.      $         LOHI,IGRAPH,IVH,NPP,0)
  403.             ENDIF
  404. * Plot the axis value at this position
  405.             IF(J.EQ.1.AND.IAX.EQ.0.AND.XY.GE.XMIN.AND.XY.LE.XMAX) THEN
  406.               IF(NDIVS.EQ.0) NDPX = MAX0(0,INT(0.1-XY))
  407.               WRITE(FMT,"('(F20.',I1,')')") NDPX
  408.               WRITE(AXVAL,FMT) XY
  409.               IF(NDIVS.EQ.0) WRITE(AXVAL,FMT) 10.**(XY)
  410.               IB = 0
  411.   40          IB = IB + 1
  412.               IF(AXVAL(IB:IB).EQ.' '.OR.AXVAL(IB:IB).EQ.'0') GOTO 40
  413.               IF(IB.GT.1) AXVAL = AXVAL(IB:LENG(AXVAL))
  414.               IF(LENG(AXVAL).EQ.1.AND.AXVAL(1:1).EQ.'.') AXVAL = '0'
  415.               IB = LENG(AXVAL)
  416.               IF(AXVAL(IB:IB).EQ.'.') AXVAL = AXVAL(1:IB-1)
  417.               Y = YMIN - FLOAT(LOHI*8)/FLOAT(MAXY)*(YMAXA-YMINA)
  418.               X = XY - FLOAT((LENG(AXVAL)-1)*LOHI*3)/
  419.      $             FLOAT(MAXX)*(XMAXA-XMINA)
  420.               CALL TEXT(X,Y,1,ITXSIZ,AXVAL,XMINA,XMAXA,YMINA,YMAXA,XMINA
  421.      $         ,YMINA,XMAXA,YMAXA,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  422.             ELSE IF(J.EQ.1.AND.IAX.EQ.1.AND.XY.GE.YMIN.AND.XY.LE.YMAX) 
  423.      $      THEN
  424.               IF(NDIVS.EQ.0) NDPY = MAX0(0,INT(0.1-XY))
  425.               WRITE(FMT,"('(F20.',I1,')')") NDPY
  426.               WRITE(AXVAL,FMT) XY
  427.               IF(NDIVS.EQ.0) WRITE(AXVAL,FMT) 10.**(XY)
  428.               IB = 0
  429.   50          IB = IB + 1
  430.               IF(AXVAL(IB:IB).EQ.' '.OR.AXVAL(IB:IB).EQ.'0') GOTO 50
  431.               IF(IB.GT.0) AXVAL = AXVAL(IB:LENG(AXVAL))
  432.               IF(LENG(AXVAL).EQ.1.AND.AXVAL(1:1).EQ.'.') AXVAL = '0'
  433.               IB = LENG(AXVAL)
  434.               IF(AXVAL(IB:IB).EQ.'.') AXVAL = AXVAL(1:IB-1)
  435.               X = XMIN - FLOAT(LOHI*8)/FLOAT(MAXX)*(XMAXA-XMINA)
  436.               Y = XY - FLOAT((LENG(AXVAL)-1)*LOHI*3)/
  437.      $             FLOAT(MAXY)*(YMAXA-YMINA)
  438.               CALL TEXT(X,Y,2,ITXSIZ,AXVAL,XMINA,XMAXA,YMINA,YMAXA,XMINA
  439.      $         ,YMINA,XMAXA,YMAXA,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  440.             ENDIF
  441.   20      CONTINUE
  442.   10    CONTINUE
  443.   30  CONTINUE
  444.       RETURN
  445.       END
  446.    
  447. *-----------------------------------------------------------------------
  448.  
  449.       SUBROUTINE PLOTD(NPTS,LTYP,MARK,MSIZE,LEGEND,IORI,ITXSIZ,
  450.      $  XX,YY,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,
  451.      $  MMAXX,MMAXY,LOHI,IGRAPH,IVH,STRNG,IFN,X1,X2,P,X,Y,ILEGND,
  452.      $  LEGPOS,NDIVX,NDIVY)
  453. *
  454. * Plot the data for this curve, or this data set.
  455. *
  456. * First plot the legend for this data set, if required
  457. *
  458.       INTEGER*2 IGRAPH
  459.       CHARACTER*80 LEGEND, STRNG
  460.       DIMENSION IGRAPH(MMAXX,MMAXY), X(*), Y(*), P(*)
  461.       IF(NPTS.GE.0.AND.(LENG(LEGEND).GT.1.OR.LEGEND(1:1).NE.' ')) THEN
  462.         ILEGND = ILEGND + 1
  463.         YY = YMAX - FLOAT(ILEGND*LOHI*15)/FLOAT(MAXY)*(YMAX-YMIN)
  464.         IF(LEGPOS.LT.1.OR.LEGPOS.GT.8) LEGPOS = 1
  465.         LEGP = LEGPOS
  466.         IF(LEGPOS.GT.4) LEGP = LEGPOS - 4
  467.         IF(LEGPOS.GT.4) YY = YMIN + FLOAT(ILEGND*LOHI*15)/FLOAT(MAXY)
  468.      $   *(YMAX-YMIN)
  469.         DX = (XMAX-XMIN)/FLOAT(MAXX)*FLOAT(LOHI)
  470.         XX = XMIN + 20.*DX + FLOAT(LEGP-1)*(XMAX-XMIN)/4.
  471.         CALL MARKPT(MARK,MSIZE,XX,YY,XMINA,XMAXA,YMINA,YMAXA,XMIN,
  472.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  473.         XX1 = XX - 15.*DX
  474.         XX2 = XX + 15.*DX
  475.         NPP = 0
  476.         IF(LTYP.NE.0) CALL LINE(IABS(LTYP),XX1,YY,XX2,YY,XMINA,XMAXA,
  477.      $   YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,
  478.      $   IGRAPH,IVH,NPP,0)
  479.         XX = XX + 20.*DX
  480.         CALL TEXT(XX,YY,1,LOHI,LEGEND,XMINA,XMAXA,YMINA,YMAXA,XMIN,
  481.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  482.       ENDIF
  483.       IF(NPTS.EQ.-2) THEN
  484. * If NPTS=-2 then clear a rectangular screen area, with optional border
  485.         IF(NDIVX.EQ.0) THEN
  486.           X(1) = ALOG10(X(1))
  487.           X(2) = ALOG10(X(2))
  488.         ENDIF
  489.         IF(NDIVY.EQ.0) THEN
  490.           Y(1) = ALOG10(Y(1))
  491.           Y(2) = ALOG10(Y(2))
  492.         ENDIF
  493.         CALL CLRBOX(X(1),Y(1),X(2),Y(2),LTYP,XMINA,XMAXA,YMINA,YMAXA,
  494.      $   XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  495.       ELSEIF(NPTS.EQ.-1) THEN
  496. * If NPTS=-1 then text is to be plotted.
  497.         IF(NDIVX.EQ.0) XX = ALOG10(XX)
  498.         IF(NDIVY.EQ.0) YY = ALOG10(YY)
  499.         CALL TEXT(XX,YY,IORI,ITXSIZ,STRNG,XMINA,XMAXA,YMINA,YMAXA,
  500.      $   XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  501.       ELSEIF(NPTS.EQ.0) THEN
  502. * If NPTS=0 then a function plot is required.
  503.         IF(NDIVX.EQ.0) THEN
  504. *-------- Log scale on x-axis, so take logs of X1, X2
  505.           X1 = ALOG10(X1)
  506.           X2 = ALOG10(X2)
  507.         ENDIF
  508.         CALL FUNCT(IFN,P,NDIVX,NDIVY,LTYP,X1,X2,XMINA,XMAXA,YMINA,
  509.      $   YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,
  510.      $   IVH)
  511.       ELSEIF(NPTS.GT.0) THEN
  512. * Plot the set of points
  513.         IF(NDIVX.EQ.0) THEN
  514. *-------- Log scale for x-axis, so take logs of x values
  515.           DO 20 J=1, NPTS
  516.             X(J) = ALOG10(X(J))
  517.   20      CONTINUE
  518.         ENDIF
  519.         IF(NDIVY.EQ.0) THEN
  520. *-------- Log scale for y-axis...
  521.           DO 30 J=1, NPTS
  522.             Y(J) = ALOG10(Y(J))
  523.   30      CONTINUE
  524.         ENDIF
  525. *------ Plot the points
  526.         CALL POINTS(MARK,MSIZE,LTYP,NPTS,X,Y,XMINA,XMAXA,YMINA,YMAXA,
  527.      $   XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH) 
  528.       ENDIF
  529.       RETURN
  530.       END
  531.  
  532. *-----------------------------------------------------------------------
  533.  
  534.       SUBROUTINE POINT(X,Y,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  535.      $ XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  536. *
  537. * Plot a single point at the coordinate (X,Y) on IGRAPH
  538. * (XMIN,YMIN) and (XMAX,YMAX) are the lower left and upper right points
  539. * of the graph being plotted.
  540. *   MAXX  = no. of dots along x-axis
  541. *   MAXY  = no. of dots along y-axis
  542. *   MMAXX = no. of columns to be printed out;
  543. *   MMAXY = (no. of graph rows)/14. 
  544. *          Each line printed prints 7 rows of the graph.
  545. *
  546. * Each integer in the array IGRAPH has 16 bits, and each bit which 
  547. * equals 1 is to be printed as a dot.  However, only 14 are used 
  548. * for various technical reasons. In other words the integer at
  549. * IGRAPH(5,2) would contain 14 dot positions corresponding to column
  550. * 5 and rows 17 to 32 of the graph to be printed on the dot matrix 
  551. * printer.  MASKHI converts for Hi-res 144 dpi vertical printing, in
  552. * which the row is printed as two interleaved rows 1/144" apart.
  553. *
  554.       INTEGER*2 IGRAPH
  555.       DIMENSION IGRAPH(MMAXX,MMAXY), MASKHI(14)
  556.       DATA MASKHI/1,8,2,9,3,10,4,11,5,12,6,13,7,14/
  557.       X = AMAX1(XMIN,AMIN1(XMAX,X))
  558.       Y = AMAX1(YMIN,AMIN1(YMAX,Y))
  559.       IF(IVH.EQ.1) THEN
  560. *------ Vertical format (normal)
  561.         ICOL = INT((X-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+1.5)
  562.         IY = INT((Y-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  563.       ELSE
  564. *------ If horizontal format selected, then transform values
  565.         ICOL = MAXY - INT((Y-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  566.         IY = INT((X-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+0.5)
  567.       ENDIF
  568.       IROW = IY/14+1
  569.       IBIT = IROW*14-IY
  570.       IF(LOHI.EQ.2) IBIT = MASKHI(IBIT)
  571.       CALL SETBIT(IGRAPH(ICOL,IROW),IBIT)
  572.       RETURN
  573.       END
  574.  
  575. *-----------------------------------------------------------------------
  576.  
  577.       SUBROUTINE MARKPT(IPT,ISIZE,X,Y,XMINA,XMAXA,YMINA,YMAXA,
  578.      $ XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  579. *
  580. * Plot a mark (symbol) of size ISIZE, centred at the point (X,Y) on IGRAPH.
  581. * The symbol shapes are stored as characters, and accessed from TEXT,
  582. * so changes to TEXT may alter these definitions.
  583. *
  584. *   IPT  =  1 : point           
  585. *           2 : open octagon    
  586. *           3 : filled  "       
  587. *           4 : open square     
  588. *           5 : filled  "       
  589. *           6 : open triangle 
  590. *           7 : filled  "
  591. *           8 : cross
  592. *           9 : plus
  593. *          10 : star
  594. *          11 : open diamond
  595. *          12 : filled  "         
  596. *      13-31  :  undefined? Might be used later. Blank for now.
  597. *      32-126 :  plot the corresponding ASCII character
  598. *                (Orientation = 1,  ISIZE = Text size)
  599. *
  600.       INTEGER*2 IGRAPH
  601.       CHARACTER*80 CH, BLNK
  602.       DIMENSION IGRAPH(MMAXX,MMAXY)
  603.       DATA BLNK /' '/
  604.       CH = BLNK
  605.       CALL POINT(X,Y,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,
  606.      $ MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  607.       IORI = 1
  608.       IF(IPT.GT.1.AND.IPT.LE.126) THEN 
  609.         CH(1:1) = CHAR(IPT)
  610.         CALL TEXT(X,Y,IORI,ISIZE,CH,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  611.      $   XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  612.       ENDIF
  613.       IF(IPT.EQ.10) THEN  
  614.         CH(1:1) = CHAR(8)
  615.         CALL TEXT(X,Y,IORI,ISIZE,CH,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  616.      $   XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  617.       ENDIF
  618.       RETURN
  619.       END        
  620.  
  621. *-----------------------------------------------------------------------
  622.  
  623.       SUBROUTINE TEXT(X,Y,IORI,ITXSIZ,STRNG,XMINA,XMAXA,YMINA,
  624.      $ YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  625. *
  626. * Plot a string of text. Also used to plot graph symbols, using character
  627. * positions 1 to 31 in the ASCII sequence to define these symbols.
  628. * (X,Y) is the centre of the capital letters (or symbols)
  629. * IORI = orientation.  1 = Normal (vertical)
  630. *                      2 = Rotated 90 deg anti-clockwise
  631. *                      3 = Upside down
  632. *                      4 = Rotated 90 deg clockwise
  633. *
  634. * IORIX = psuedo-orientation, corrected for IVH
  635. * ITXSIZ= Text size, 1 to n. (Steps of two for lo-res : 2, 4, 6, ...)
  636. *
  637.       INTEGER*2 IGRAPH, ICH, NB, NI, CHARS
  638.       CHARACTER*80 STRNG
  639.       CHARACTER CH
  640.       DIMENSION IGRAPH(MMAXX,MMAXY), CHARS(3,126), MASK2(16), 
  641.      $ IDOTS(10,0:6)
  642.       DATA MASK2/1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,
  643.      $           32768/
  644.       DATA CHARS/    0,    0,    0, 4208, 1090, 7185,28784, 1987, 7199,
  645.      $            4344, 1090,15889,
  646.      $           28920, 1987,15903, 8240, 1153, 3082,24624, 1921, 3086,
  647.      $            8328,  257, 8714,16416, 1984, 2052,16416, 1984, 2052,
  648.      $            8224, 1089, 2058,24608, 1985, 2062,    0,    0,    0,
  649.      $               0,    0,    0,    0,    0,    0,    0,    0,    0,
  650.      $               0,    0,    0,    0,    0,    0,    0,    0,    0,
  651.      $               0,    0,    0,    0,    0,    0,    0,    0,    0,
  652.      $               0,    0,    0,    0,    0,    0,    0,    0,    0,
  653.      $               0,    0,    0,    0,    0,    0,    0,    0,    0,
  654.      $               0,    0,    0,    0,    0,    0,    0,    0,    0,
  655.      $               0,    0,    0,    0, 4000,    0,    0,    7,   56,
  656.      $           30800,17031, 5183,20552, 4066, 9237, 8584,16646, 8969,
  657.      $           18648, 2724, 1297,    0, 3077,    0,    0,18368,   32,
  658.      $            2048, 1988,    0,24648, 2016, 4614,16416, 1984, 2052,
  659.      $            6656,  112,    0,16416,  256, 2052, 6144,   96,    0,
  660.      $            8200,  256, 8200, 2296,18468,15904, 2048,20450,    0,
  661.      $            6276,18596,12580,18692,19236,17972, 8240,17537, 1087,
  662.      $            2504,18981,20008,18552,18722, 1572,  256, 2532,24616,
  663.      $           18648,18724,13860,18624, 2340,15397,22528,  865,    0,
  664.      $           23040,  881,    0, 8224,17473,   32, 8272,  641, 5130,
  665.      $            2048, 1092, 2058,  128, 2212,12324, 2296,19364,15658,
  666.      $            8316, 2178, 7954,30980,18727,13860, 2296,18468, 8736,
  667.      $           30980,18471,15904,18940,18724,16676,16892, 2308,16420,
  668.      $            2296,18468,20004,16892,  256,32516, 2048,20452,   32,
  669.      $            2056, 2080,16447,16892,  640,16657, 2556,16416,  256,
  670.      $             508,  770,32528,  508,  514,32516, 2296,18468,15904,
  671.      $           16892, 2308,12324, 2296,18596,16161,16892, 2436,12581,
  672.      $           18632,18724, 9764,  256, 4068,16416, 2552,16416,32256,
  673.      $            4592,   32,31745, 2552,16832,32256, 8588,  257,25354,
  674.      $             384,  481,24584,10508,18724,24872,30720,18471,   32,
  675.      $             128,  257,  514, 2048,18468,   63,   64, 2050, 4112,
  676.      $             513, 4104,   64,    0, 3072,   40,10248,17057, 3850,
  677.      $            2556,16929, 3592, 2104,16929, 4360, 2104,16929,32520,
  678.      $           10296,17057, 3338,30752, 2307,   36, 2617,21033, 8072,
  679.      $             508,  513, 3848, 2048,19425,    0,  513,25096,   47,
  680.      $            8700,  384,  265, 2048,20452,    0,   60,  481, 3848,
  681.      $             124,  513, 3848, 2104,16929, 3592, 2175,16929, 3592,
  682.      $            2104,16929, 8136,16508,  512, 4104,10276,17057, 4618,
  683.      $           28736,16935,  520, 2168,16416, 7936, 4208,   32, 7169,
  684.      $            2168,16576, 7680,20548,  128, 4357, 2680,20520, 8064,
  685.      $            6212,17057, 4364,16384,18112,16672,    0, 3808,    0,
  686.      $            2308, 1732,    4,  128, 1028, 8200/
  687.       ISIZE = MAX0(1,(ITXSIZ*LOHI+1)/2)
  688.       IF(IORI.LT.1.OR.IORI.GT.4) IORI = 1
  689. * Calc centre of first character, by analogy with POINT.
  690. * First calc integer limits of plotting area
  691.       IF(IVH.EQ.1) THEN
  692.         IMINX = INT((XMIN-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+1.5)
  693.         IMAXX = INT((XMAX-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+1.5)
  694.         IMINY = INT((YMIN-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  695.         IMAXY = INT((YMAX-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  696.         IORIX = IORI
  697.         IX = INT((X-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+1.5)
  698.         IY = INT((Y-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  699.       ELSE
  700.         IMINX = INT((XMIN-XMINA)/(XMAXA-XMINA)*FLOAT(MAXY-1)+0.5)
  701.         IMAXX = INT((XMAX-XMINA)/(XMAXA-XMINA)*FLOAT(MAXY-1)+0.5)
  702.         IMINY = INT((YMIN-YMINA)/(YMAXA-YMINA)*FLOAT(MAXX-1)+1.5)
  703.         IMAXY = INT((YMAX-YMINA)/(YMAXA-YMINA)*FLOAT(MAXX-1)+1.5)
  704.         IORIX = IORI + 1
  705.         IF(IORIX.GT.4) IORIX = 1
  706.         IX = MAXY - INT((Y-YMINA)/(YMAXA-YMINA)*FLOAT(MAXY-1)+0.5)
  707.         IY = INT((X-XMINA)/(XMAXA-XMINA)*FLOAT(MAXX-1)+0.5)
  708.       ENDIF
  709.       DO 60 I=1, LENG(STRNG)
  710. * Calc bottom left of this character
  711.         GOTO(10,20,30,40) IORIX
  712.   10    IC = IX + (I*6-9)*ISIZE
  713.         IR = IY - 6*ISIZE
  714.         GOTO 50
  715.   20    IC = IX + 6*ISIZE
  716.         IR = IY + (I*6-9)*ISIZE
  717.         GOTO 50
  718.   30    IC = IX + (9-I*6)*ISIZE
  719.         IR = IY + 6*ISIZE
  720.         GOTO 50
  721.   40    IC = IX - 6*ISIZE
  722.         IR = IY + (9-I*6)*ISIZE
  723. * Plot the character
  724.   50    IF(ISIZE.GT.1) THEN
  725.           DO 200 J=1, 10
  726.             DO 210 K=0, 6
  727.               IDOTS(J,K) = 0
  728.  210        CONTINUE
  729.  200      CONTINUE
  730.         ENDIF  
  731.         CH = STRNG(I:I)
  732.         ICH = ICHAR(CH)
  733.         DO 70 J=1, 5
  734.           DO 80 K=1, 9
  735.             NI = (J*9+K+5)/15
  736.             NB = J*9+K+6-15*NI
  737.             IF(MOD(CHARS(NI,ICH),MASK2(NB+1)).GE.MASK2(NB)) THEN
  738.               CALL CHRDOT(IORIX,IC,IR,J*ISIZE,K*ISIZE,LOHI,
  739.      $         IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  740.               IDOTS(K,J) = 1
  741.             ENDIF
  742.   80      CONTINUE
  743.   70    CONTINUE
  744.         IF(ISIZE.GT.1) THEN
  745.           DO 320 ISZ=1, ISIZE-1
  746.             DO 300 J=1, 5
  747.               DO 310 K=1, 9
  748.                 JJ = ISIZE*J
  749.                 KK = ISIZE*K
  750.                 IICH = 0
  751.                 IF(ICH.EQ.3.OR.ICH.EQ.5.OR.ICH.EQ.7.OR.ICH.EQ.12) IICH=1
  752.                 IF (IDOTS(K,J).EQ.1) THEN
  753.                   IF(IDOTS(K,J+1).EQ.1) CALL CHRDOT(IORIX,IC,IR,JJ+ISZ,
  754.      $             KK,LOHI,IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  755.                   IF(IDOTS(K+1,J).EQ.1) THEN
  756.                     CALL CHRDOT(IORIX,IC,IR,JJ,KK+ISZ,LOHI,
  757.      $               IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  758.                   ELSE
  759.                     IF(IDOTS(K,J+1).NE.1.AND.IDOTS(K+1,J+1).EQ.1) CALL
  760.      $               CHRDOT(IORIX,IC,IR,JJ+ISZ,KK+ISZ,LOHI,
  761.      $               IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  762.                     IF(IDOTS(K,J-1).NE.1.AND.IDOTS(K+1,J-1).EQ.1) CALL
  763.      $               CHRDOT(IORIX,IC,IR,JJ-ISZ,KK+ISZ,LOHI,
  764.      $               IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  765.                   ENDIF  
  766.                   IF(IICH.EQ.1) THEN
  767.                     IF(IDOTS(K+1,J+1).EQ.1) CALL CHRDOT(IORIX,IC,IR,
  768.      $   JJ+ISZ,KK+ISZ,LOHI,IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  769.                     IF(IDOTS(K+1,J-1).EQ.1) CALL CHRDOT(IORIX,IC,IR,
  770.      $   JJ-ISZ,KK+ISZ,LOHI,IMINX,IMAXX,IMINY,IMAXY,MMAXX,MMAXY,IGRAPH)
  771.                   ENDIF
  772.                 ENDIF
  773.  310          CONTINUE
  774.  300        CONTINUE
  775.  320      CONTINUE
  776.         ENDIF  
  777.   60  CONTINUE
  778.       RETURN
  779.       END
  780.  
  781. *-----------------------------------------------------------------------
  782.  
  783.       SUBROUTINE LINE(LTYP,X1,Y1,X2,Y2,XMINA,XMAXA,YMINA,YMAXA,
  784.      $ XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,
  785.      $ IFPBL)
  786. *
  787. * Plot a line from (X1,Y1) to (X2,Y2) on IGRAPH.
  788. * Calls POINT to plot the individual points.
  789. *
  790. * LTYP  = Line type : 1 =  continuous line
  791. *                     2 =  .................
  792. *                     3 =  . . . . . . . . .
  793. *                     4 =  - - - - - - - - -
  794. *                     5 =  -- . -- . -- . --
  795. *
  796. * NPP is the number of points plotted.
  797. * IFPBL = 0 to print both end-points of the line, 
  798. *         else blank first end-point (for plotting chains of lines)
  799. * DOT(ijk) = Array of patterns for dotted lines
  800. *            i=0 or 1 for dot or no dot, j=LTYP, k=LOHI
  801. *
  802.       INTEGER*2 IGRAPH
  803.       DIMENSION IGRAPH(MMAXX,MMAXY), DOT(12,5,2)
  804.       DATA DOT/1,1,1,1,1,1,1,1,1,1,1,1,
  805.      $         1,0,1,0,1,0,1,0,1,0,1,0,
  806.      $         1,0,0,1,0,0,1,0,0,1,0,0,
  807.      $         1,1,1,1,0,0,1,1,1,1,0,0,
  808.      $         1,1,1,0,1,0,1,1,1,0,1,0,
  809.      $         1,1,1,1,1,1,1,1,1,1,1,1,
  810.      $         1,0,0,1,0,0,1,0,0,1,0,0,
  811.      $         1,0,0,0,0,0,1,0,0,0,0,0,
  812.      $         1,1,1,1,1,1,1,1,0,0,0,0,
  813.      $         1,1,1,1,1,1,1,0,0,1,0,0/
  814.       IF(NPP.LT.1) NPP = 1
  815.       IF(LTYP.LT.0.OR.LTYP.GT.5) LTYP = 1
  816. * Calc min. no. of points for an unbroken line
  817.       PNTS = ABS((X2-X1)/(XMAXA-XMINA)*(MAXX-1))
  818.       PNTS = AMAX1(1.,PNTS,ABS((Y2-Y1)/(YMAXA-YMINA)*(MAXY-1)))
  819.       IPNTS = INT(PNTS+0.5)
  820.       DX = (X2-X1)/PNTS
  821.       DY = (Y2-Y1)/PNTS
  822.       ISTART = IFPBL
  823.       IF(ISTART.NE.0) ISTART = 1
  824.       DO 10 I=ISTART, IPNTS
  825.         IF(NPP.GT.12) NPP = 1
  826.         IF(DOT(NPP,LTYP,LOHI).EQ.1) THEN
  827.           X = X1 + I*DX
  828.           Y = Y1 + I*DY
  829.           CALL POINT(X,Y,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,
  830.      $     MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  831.         ENDIF
  832.         NPP = NPP + 1
  833.   10  CONTINUE
  834.       RETURN
  835.       END
  836.  
  837. *-----------------------------------------------------------------------
  838.  
  839.       SUBROUTINE SORT(NPTS,X,Y)
  840. *
  841. * Sort the data pairs into ascending order
  842. *
  843.       DIMENSION X(*),Y(*)
  844.       M = NPTS
  845.       L = M/2 + 1
  846.   10  IF(L.GT.1) THEN
  847.         L = L - 1
  848.         XX = X(L)
  849.         YY = Y(L)
  850.       ELSE
  851.         XX = X(M)
  852.         YY = Y(M)
  853.         X(M) = X(1)
  854.         Y(M) = Y(1)
  855.         M = M - 1
  856.         IF(M.EQ.1) GOTO 30
  857.       ENDIF
  858.       I = L
  859.       J = 2*L
  860.       IF(J.LE.M) THEN
  861.   20    IF(J.LT.M.AND.X(J).LT.X(J+1)) J = J+1
  862.         IF(XX.LT.X(J)) THEN
  863.           X(I) = X(J)
  864.           Y(I) = Y(J)
  865.           I = J
  866.           J = 2*J
  867.         ELSE
  868.           J = M + 1
  869.         ENDIF
  870.         IF(J.LE.M) GO TO 20
  871.       ENDIF
  872.       X(I) = XX
  873.       Y(I) = YY
  874.       GO TO 10
  875.   30  X(1) = XX
  876.       Y(1) = YY
  877.       RETURN
  878.       END
  879.  
  880. *-----------------------------------------------------------------------
  881.  
  882.       SUBROUTINE SPLINE(NPIN,NPOUT,X,Y,XX,YY)
  883. *
  884. * Fit a cubic spline to the npin (x,y) pairs, and return npout evenly 
  885. * spaced fitted (xx,yy) data pairs. Also returns sorted (x,y)           
  886. *
  887.       DIMENSION X(*), Y(*), XX(*), YY(*), S(500), C(500)
  888.       CALL SORT(NPIN,X,Y)
  889.       AI = X(2)-X(1) 
  890.       PI = (Y(2)-Y(1))/AI 
  891.       S(1) = -1 
  892.       C(1) = 0 
  893.       DI = -AI 
  894.       CI = 0
  895.       DO 10 I=2,NPIN-1
  896.         A1 = X(I+1)-X(I) 
  897.         Z = 2*(A1+AI)-DI 
  898.         P2 = (Y(I+1)-Y(I))/A1
  899.         C(I) = (6*(P2-PI)-CI)/Z
  900.         CI = C(I)*A1 
  901.         PI = P2
  902.         S(I) = A1/Z 
  903.         DI = S(I)*A1 
  904.         AI = A1
  905.   10  CONTINUE
  906.       S(NPIN) = C(NPIN-1)/(1+S(NPIN-1)) 
  907.       J = NPIN
  908.       DO 20 I=1,NPIN-1
  909.         J = J-1
  910.         S(J) = C(J)-S(J)*S(J+1) 
  911.   20  CONTINUE
  912.       IF(NPOUT.GT.500) NPOUT = 500
  913.       DX = (X(NPIN)-X(1))/(NPOUT-1) 
  914.       XX(1) = X(1) 
  915.       YY(1) = Y(1) 
  916.       J = 1
  917.       DO 30 I=1,NPIN-1 
  918.         IF(XX(J)+DX.LT.X(I+1)) THEN
  919.   40      J = J+1 
  920.           XX(J) = XX(J-1)+DX
  921.           XV = XX(J)-X(I) 
  922.           T = 2*S(I)+XV*(S(I)-S(I+1))/(X(I)-X(I+1))+S(I+1)
  923.           YY(J)=Y(I)+XV*((Y(I)-Y(I+1))/(X(I)-X(I+1))+(XX(J)-X(I+1))*T/6)
  924.           IF(XX(J)+DX.LT.X(I+1)) GOTO 40
  925.         ENDIF
  926.   30  CONTINUE
  927.       XX(NPOUT) = X(NPIN) 
  928.       YY(NPOUT) = Y(NPIN)
  929.       RETURN
  930.       END
  931.  
  932. *-----------------------------------------------------------------------
  933.  
  934.       SUBROUTINE POINTS(IPT,ISIZE,LTYP,NPTS,X,Y,XMINA,XMAXA,
  935.      $ YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,
  936.      $ IGRAPH,IVH)
  937. *
  938. * Plot an array of points [X(i),Y(i)] on IGRAPH
  939. *
  940. * IPT   = Type of mark to be plotted at each point (see MARKPT)
  941. * ISIZE = Size of mark
  942. *
  943. * LTYP  = Line type.  0 = plot points only
  944. *                    >0 = fit data with straight line segments
  945. *                    <0 = fit data with a cubic spline
  946. *        
  947. * NPTS  = No of points to be plotted
  948. *
  949.       INTEGER*2 IGRAPH
  950.       DIMENSION X(*), Y(*), IGRAPH(MMAXX,MMAXY), XX(500), YY(500)
  951.       DO 10 I=1, NPTS
  952.         CALL MARKPT(IPT,ISIZE,X(I),Y(I),XMINA,XMAXA,YMINA,YMAXA,XMIN,
  953.      $   YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH)
  954.   10  CONTINUE 
  955.       NPP = 1
  956.       IF(LTYP.GT.0) THEN
  957.         DO 20 I=2,NPTS
  958.           CALL LINE(LTYP,X(I-1),Y(I-1),X(I),Y(I),XMINA,XMAXA,YMINA,
  959.      $     YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,
  960.      $     IVH,NPP,1)
  961.   20    CONTINUE
  962.       ELSEIF(LTYP.LT.0) THEN   ! Spline fit
  963. *------ First sort into ascending x values, then calc and plot the spline
  964.         NP = INT(ABS((X(NPTS)-X(1))/(XMAXA-XMINA)*(MAXX-1)/5.))
  965.         CALL SPLINE(NPTS,NP,X,Y,XX,YY)
  966.         DO 30 I=2, NP
  967.           CALL LINE(-LTYP,XX(I-1),YY(I-1),XX(I),YY(I),XMINA,XMAXA,
  968.      $     YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,
  969.      $     LOHI,IGRAPH,IVH,NPP,1)
  970.   30    CONTINUE
  971.       ENDIF         
  972.       RETURN
  973.       END
  974.  
  975. *-----------------------------------------------------------------------
  976.  
  977.       SUBROUTINE FUNCT(IFN,P,NDIVX,NDIVY,LTYP,X1,X2,XMINA,
  978.      $ XMAXA,YMINA,YMAXA,XMIN,YMIN,XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,
  979.      $ LOHI,IGRAPH,IVH) 
  980. *
  981. * Plot a continuous function from X1 to X2 on IGRAPH
  982. *
  983. * NDIVX, NDIVY = 0 for log. scale on X or Y axis, >0 for linear scale.
  984. * IFN   = Function number
  985. * LTYP  = Line type (solid, dotted etc)
  986. *
  987.       INTEGER*2 IGRAPH
  988.       DIMENSION IGRAPH(MMAXX,MMAXY), P(*)
  989.       IPNTS = INT(ABS((X2-X1)/(XMAXA-XMINA)*(MAXX-1)/4.))
  990.       IF(IPNTS.LT.1) IPNTS = 1
  991.       XB = X1
  992. * Take logs as necessary if log scales specified
  993.       IF(NDIVX.GT.0) YB = FGRAPH(IFN,P,X1)
  994.       IF(NDIVX.EQ.0) YB = FGRAPH(IFN,P,10.**X1)
  995.       IF(NDIVY.EQ.0) YB = ALOG10(YB)
  996.       DX = (X2-X1)/FLOAT(IPNTS)
  997.       NPP = 1
  998.       DO 10 I=1, IPNTS
  999.         XA = XB
  1000.         YA = YB
  1001.         XB = X1 + I*DX
  1002.         IF(NDIVX.GT.0) YB = FGRAPH(IFN,P,XB)
  1003.         IF(NDIVX.EQ.0) YB = FGRAPH(IFN,P,10.**XB)
  1004.         IF(NDIVY.EQ.0) YB = ALOG10(YB)
  1005.         CALL LINE(LTYP,XA,YA,XB,YB,XMINA,XMAXA,YMINA,YMAXA,XMIN,YMIN,
  1006.      $   XMAX,YMAX,MAXX,MAXY,MMAXX,MMAXY,LOHI,IGRAPH,IVH,NPP,1)
  1007.   10  CONTINUE
  1008.       RETURN
  1009.       END
  1010.  
  1011. *-----------------------------------------------------------------------
  1012.  
  1013.       SUBROUTINE CLRGRF(MMAXX,MMAXY,IGRAPH)
  1014. *
  1015. * Set IGRAPH to zero - ie clear the graph
  1016. *
  1017.       INTEGER*2 IGRAPH
  1018.       DIMENSION IGRAPH(MMAXX,MMAXY)
  1019.       DO 10 ICOL=1, MMAXX
  1020.         DO 20 IROW=1, MMAXY
  1021.           IGRAPH(ICOL,IROW) = 0
  1022.   20    CONTINUE
  1023.   10  CONTINUE
  1024.       RETURN
  1025.       END
  1026.  
  1027. *-----------------------------------------------------------------------
  1028.  
  1029.       SUBROUTINE CHRDOT(IORIX,IC,IR,J,K,LOHI,IMINX,IMAXX,IMINY,
  1030.      $ IMAXY,MMAXX,MMAXY,IGRAPH)
  1031.       INTEGER*2 IGRAPH
  1032.       DIMENSION IGRAPH(MMAXX,MMAXY), MASKHI(14)
  1033.       DATA MASKHI/1,8,2,9,3,10,4,11,5,12,6,13,7,14/
  1034. *
  1035. * Set this dot to on (for plotting characters). Called by TEXT
  1036. * IC,IR : Col, row for bottom left of character
  1037. * J,K   : Offset in dots to current dot position
  1038. *
  1039.       GOTO(110,120,130,140) IORIX
  1040.  110  ICOL = IC + J
  1041.       IROW = IR + K
  1042.       GOTO 150
  1043.  120  ICOL = IC - K
  1044.       IROW = IR + J
  1045.       GOTO 150
  1046.  130  ICOL = IC - J
  1047.       IROW = IR - K
  1048.       GOTO 150
  1049.  140  ICOL = IC + K
  1050.       IROW = IR - J
  1051.  150  IF(ICOL.GT.IMINX.AND.ICOL.LT.IMAXX.AND.IROW.GT.IMINY.AND.IROW.
  1052.      $ LT.IMAXY) THEN
  1053.         IRR = IROW/14+1
  1054.         IBIT = IRR*14-IROW
  1055.         IF(LOHI.EQ.2) IBIT = MASKHI(IBIT)
  1056.         CALL SETBIT(IGRAPH(ICOL,IRR),IBIT)
  1057.       ENDIF
  1058.       RETURN
  1059.       END
  1060.  
  1061. *-----------------------------------------------------------------------
  1062.  
  1063.       FUNCTION LENG(STRING)
  1064. *
  1065. * Returns the length of STRING, excluding trailing blanks
  1066. *
  1067.       CHARACTER*80 STRING
  1068.       I = LEN(STRING)
  1069.       IF(I.LE.1) GOTO 20
  1070.   10  I = I - 1
  1071.       IF(STRING(I:I).EQ.' '.AND.I.GT.1) GOTO 10
  1072.   20  LENG = I
  1073.       RETURN
  1074.       END
  1075.  
  1076. *-----------------------------------------------------------------------
  1077.