(*********************************************************************
 
    :Program.  	 GraphicLib.mod
    :Author.   	 Thomas E. Speer (PLOT V3.3)
    :Author.     Anpassung an AMIGA, Gary Struhlik
    :Version.  	 1.3
    :Date.     	 10.09.1989
    :Copyright.  Aus dem original TURBO PASCAL Source code:
    :Copyright.  ------------------------------------------
    :Copyright.  Copyright 1984 by Thomas E. Speer 
    :Copyright.  All rights reserved (PLOT V3.3,SIG/M 194)
    :Copyright.  Released to the Public Domain for Non-commercial use only
    :Language. 	 Modula-II
    :Translator. M2Amiga 3.2d
    :Imports.	 UNIXPlot [Joel Swank] [gs]
    :Contents.   2D-Koordinatenkreuze als UNIX plot file speichern
    :Remark.	 Für den Amiga Modula-2 Klub / Stuttgart
    :Remark.     Die   meisten   in   dieser   Grafik-Bibliothek   enthaltenen
    :Remark.     Unterprogramme wurden von Thomas E.Speer in der Public Domain
    :Remark.     Serie SIG/M  194 veröffentlicht. Diese wurden in TURBO PASCAL
    :Remark.     unter dem Betriebssystem CP/M erstellt.
    :Remark.     Die  Übersetzung  in   MODULA2  dieser  Bibliothek  wurde  von
    :Remark.     Gary Struhlik vorgenommen. 
    :Remark.     
    :History.      14.10.1988 V1.0.0 erste lauffähige Version
    :History.      20.11.1988 V1.1.0 um HardCopy ergänzt
    :History.      19.12.1988 V1.2.0 HardCopy verbessert (nur Epson ESC/P)
    :History.      08.01.1989 V1.2.1 xpos, ypos importierbar
    :History.    > 14.01.1989 V1.2.2 kleinere Bugs entfernt
    :History.      19.08.1989 V1.2.3 HardCopy unterstützt jetzt WB 1.3 !
    :History.      20.08.1989 V1.2.4 erster Versuch UNIX Plot-Files zu erzeugen
    :History.    > 10.09.1989 V1.3.0 jetzt  werden nur noch UNIX plot files er-
    :History.                        zeugt

***************************************************************)

IMPLEMENTATION MODULE GraphicLib;

FROM SYSTEM IMPORT ADR,BITSET,LONGSET,INLINE;
FROM RealConversions IMPORT RealToStr;
FROM Strings IMPORT Length;
FROM MathLib0 IMPORT sin,cos,arctan,exp,ln,sqrt;                      
FROM InOut IMPORT WriteLn, WriteString;
IMPORT UNIXPlot;

CONST
 ln10 = 2.302585;    (*  2.302585092994045  *)  

VAR
 libname   : STRING;
 scale     : ARRAY [1..4] OF REAL;
 chxsz,chysz,chrot : REAL;
 nxchar,nychar,nxline : INTEGER;
 xmin,xmax,ymin,ymax,sxleft,sxrt,sybot,sytop : REAL;

PROCEDURE PwrOfTen ( x : REAL ) : REAL;
BEGIN
   RETURN exp(x*ln10)
END PwrOfTen;

PROCEDURE log ( x : REAL ) : REAL;
BEGIN
   RETURN ln(x)/ln10
END log;

PROCEDURE ClrGraphic; (* löschen *)
BEGIN
	UNIXPlot.erase;
END ClrGraphic;

PROCEDURE GraphOn( Filename : ARRAY OF CHAR);  (* Ein UNIX plot file öffnen *)
BEGIN
    UNIXPlot.openpl(Filename);
    UNIXPlot.space(0,0,10000,10000); (* Koordinatenfeld festlegen *)
    ClrGraphic; (* löschen *)
END GraphOn;

PROCEDURE GraphOff;  (* UNIX plot file schließen *) 
BEGIN
 UNIXPlot.closepl;
END GraphOff;

PROCEDURE InitCharSize;
BEGIN
	chxsz:=0.0125; chysz:=0.0470; chrot:=0.0;
	scale[1]:=1.0; scale[2]:=1.0; scale[3]:=1.0; scale[4]:=0.0
END InitCharSize;

PROCEDURE UnixXY( x : REAL) : INTEGER; (* Umwandlung des  definierten *)
                                       (* Zeichenquadrates   in   das *)
                                       (* UNIX plot file Zeichenfeld  *)
BEGIN
	RETURN( INTEGER(x*10000.0))
END UnixXY;	

PROCEDURE gmove( x,y :REAL); (* bewege Zeiger absolut *)
BEGIN
	UNIXPlot.move( UnixXY(x), UnixXY(y) )
END gmove; 

PROCEDURE vector( x,y : REAL); (* bewege Zeiger absolut und zeichne dabei *)
BEGIN
	UNIXPlot.cont( UnixXY(x), UnixXY(y) )
END vector;

PROCEDURE ChSet ( xsize,ysize, theta : REAL); (* Zeichengröße *)
VAR
	t : REAL;
BEGIN
	chxsz:=xsize;
	chysz:=ysize;
	chrot:=theta;
	t:=theta/57.29578;
	scale[3]:=cos(t);
	scale[4]:=sin(t)
END ChSet;

PROCEDURE tcharData; (* $E- Daten für Vektor-Zeichensatz *)
BEGIN
       INLINE( 
	255,  56, 181,  51, 178, 255,  40, 166,  72, 198, 255,  40,
	162,  72, 194,   6, 230,   4, 228, 255,  56, 178,  87, 151,   
	134, 149, 213, 228, 211, 147, 255, 104, 130,   8, 168, 166,
	134, 136,  68, 228, 226, 194, 196, 255,  98, 151, 168, 184,
	199, 198, 148, 147, 162, 178, 212, 255,   6, 151, 152, 136,
	135, 151, 255,  72, 182, 180, 194, 255,  40, 182, 180, 162,	
	255,  21, 213,  39, 195,  71, 163, 255,  55, 179,  21, 213,
	255,  17, 162, 163, 147, 146, 162, 255,  21, 213, 255,  34,
	163, 147, 146, 162, 255,  88, 146, 255,  40, 200, 214, 212,
	194, 162, 148, 150, 168, 255,  38, 184, 178,  34, 194, 255,
	 23, 168, 200, 215, 214, 147, 146, 210, 255,  23, 168, 200,
	215, 214, 197, 212, 211, 194, 162, 147, 255,  72, 194,  55,
	148, 212, 255,  88, 152, 150, 198, 213, 211, 194, 162, 147,
	255,  87, 200, 168, 151, 147, 162, 194, 211, 212, 197, 165,
	148, 255,  24, 216, 162, 255,  37, 197, 212, 211, 194, 162,
	147, 148, 165, 150, 151, 168, 200, 215, 214, 197, 255,  19,
	162, 194, 211, 215, 200, 168, 151, 150, 165, 197, 214, 255,
	 23, 167, 166, 150, 151,  20, 164, 163, 147, 148, 255,  17,
	162, 163, 147, 146, 162,  22, 166, 165, 149, 150, 255,  87,
	149, 211, 255,  22, 214,  20, 212, 255,  23, 213, 147, 255,
	 23, 168, 200, 215, 214, 180,  50, 177, 255,  23, 168, 200,
	215, 211, 194, 162, 147, 148, 165, 181, 178, 255,   2, 184,
	226,  20, 212, 255,   5, 197, 212, 211,	194, 130, 136, 200,
	215, 214, 197, 255,  87, 200, 152, 135, 131, 146, 194, 211,
	255,   2, 136, 200, 214, 212, 194, 130, 255,  88, 136, 130,
	210,  53, 133, 255,  88, 136, 130,  53, 133, 255,  87, 200,
	152, 135, 131, 146, 194, 211, 213, 181, 255,   2, 136,  88,   
	210,  85, 133, 255,  40, 200,  56, 178,  34, 194, 255,  20,
	147, 162, 178, 195, 200,  56, 216, 255,   8, 130,  88, 133,
	210, 255,  24, 146, 210, 255,   2, 136, 181, 232, 226, 255,
	  2, 136, 226, 232, 255,   7, 152, 216, 231, 227, 210, 146,	
	131, 135, 255,   2, 136, 200, 215, 214, 197, 133, 255,   7,
	152, 216, 231, 228, 194, 146, 131, 135,  68, 226, 255,   2,
	136, 200, 215, 214, 197, 133,  53, 210, 255,  87, 200, 152,
	135, 134, 149, 197, 212, 211, 194, 146, 131, 255,   8, 232,
	 56, 178, 255,  24, 147, 162, 194, 211, 216, 255,   8, 178,
	232, 255,   8, 146, 181, 210, 232, 255,   8, 226, 104, 130,
	255,  24, 180, 178,  88, 180, 255,   8, 232, 130, 226, 255,
	 88, 184, 178, 210, 255,  24, 210, 255,  24, 184, 178, 146,
	255,  22, 184, 214, 255,   0, 224, 255, 102, 215, 216, 232,
	231, 215, 255,   5, 150, 182, 197, 195, 178, 146, 131, 148,
	196,  67, 210, 255,  24, 146, 194, 211, 212, 197, 149, 255,
	 85, 165, 148, 147, 162, 210, 255,  88, 210, 162, 147, 148,
	165, 213, 255,  82, 162, 147, 148, 165, 197, 212, 148, 255,
	 87, 200, 184, 167, 162,  21, 197, 255,  17, 160, 176, 193,
	197, 165, 148, 147, 162, 194, 255,  18, 152,  21, 181, 196,
	194, 255,  50, 181,  55, 184, 255,  18, 145, 160, 176, 193,
	197,  71, 200, 255,  24, 146,  20, 199,  37, 210, 255,  40,
	184, 178,  34, 194, 255,   2, 133,   4, 149, 165, 180, 178,
	 52, 197, 213, 228, 226, 255,  18, 149,  20, 165, 197, 212,
	210, 255,  20, 165, 197, 212, 211, 194, 162, 147, 148, 255,
	 16, 149, 197, 212, 211, 194, 146, 255,  80, 213, 165, 148,   
	147, 162, 210, 255,  18, 149,  20, 165, 181, 196, 255,  19,
	162, 194, 211, 196, 164, 149, 166, 198, 213, 255,  40, 163,
	178, 194, 211, 212,  22, 182, 255,  21, 147, 162, 194, 211,
	213,  83, 226, 255,  21, 178, 213, 255,  21, 162, 180, 194,	
	213, 255,  21, 194,  18, 197, 255,  21, 178,  85, 178, 161,
	144, 255,  21, 213, 146, 210, 255,  72, 184, 167, 166, 149,
	164, 163, 178, 194, 255,  48, 184, 255,  40, 184, 199, 198,
	213, 196, 195, 178, 162, 255,   7, 152, 168, 198, 214, 231,
	255)
END tcharData;

PROCEDURE icharData; (* $E- *)	
BEGIN
       INLINE(
	  1,   2,   7,  12,  21,  32,  45,  57,  64,  69,  74,  81,
	 86,  93,  96, 102, 105, 115, 121, 130, 142, 148, 158, 171,   
	175, 192, 205, 216, 228, 232, 237, 241, 250, 263, 269, 281,
	290, 298, 305, 311, 322, 329, 336, 345, 351, 355, 361, 366,
	376, 384, 396, 406, 419, 424, 431, 435, 441, 446, 452, 457,
	462, 465, 470, 474, 477, 484, 497, 505, 512, 520, 529, 537,	
	548, 555, 560, 569, 576, 582, 595, 603, 613, 621, 629, 636,
	647, 656, 665, 669, 675, 680, 687, 692, 702, 705, 715 )
END icharData;

PROCEDURE gchar( cx,cy : REAL; charin : CHAR); (* zeichne Vektorzeichen *)

VAR
	tchar : POINTER TO ARRAY [1..721] OF INTEGER;
	ichar : POINTER TO ARRAY [1..95] OF INTEGER;
	schar,cmd,ix,iy : INTEGER;
	i : INTEGER;
	x,y,t : REAL;
BEGIN
	tchar:=ADR(tcharData);
	ichar:=ADR(icharData);	
	schar:=UNIXPlot.AndInt( ORD(charin),127);
	IF (schar>=32) THEN	
	  i:=schar-31;
	  i:=ichar^[i];
	  WHILE tchar^[i] < 255 DO
	    cmd:=tchar^[i];
	    i:=i+1;
	    iy:=UNIXPlot.AndInt(cmd, 15);
	    ix:=UNIXPlot.AndInt(cmd,112);
	    ix:=ix DIV 16;
	    x:=REAL(ix)*chxsz/7.0;
	    y:=REAL(iy)*chysz/9.0;
	    t:=x;
	    x:=cx + scale[3]*t - scale[4]*y;
	    y:=cy + scale[4]*t + scale[3]*y;
	    IF (cmd < 128) THEN
	       gmove(x,y)
	    ELSE
	       vector(x,y)
            END
	  END
	END
END gchar;

PROCEDURE gwrite(x,y : REAL; chars : textline); (* zeichne Vektorzeichenkette *)
VAR
	i : INTEGER;
BEGIN
	FOR i:=0 TO Length(chars)-1 DO
	  gchar(x,y, chars[i]);		
	  x:=x+chxsz*scale[3];
	  y:=y+chxsz*scale[4]
	END
END gwrite;

PROCEDURE rx( sxi : REAL ) : REAL; (* Bildkoordinate => Realkoordinate *)
BEGIN
	RETURN scale[1]*(sxi-sxrt) + xmin
END rx;

PROCEDURE ry( syi : REAL ) : REAL; (* siehe rx *)
BEGIN
	RETURN scale[2]*(syi-sybot) + ymin
END ry;

PROCEDURE sx( rxi : REAL ) : REAL; 
	(* Realkoordinate => Bildschirmkoordinate *)
BEGIN
	RETURN (rxi-xmin)/scale[1]+sxleft
END sx;

PROCEDURE sy( ryi : REAL ) : REAL; (* siehe sx *)
BEGIN
	RETURN (ryi-ymin)/scale[2]+sybot
END sy;

PROCEDURE swindo( sxlti,sxrti,syboti,sytopi : REAL ); (* Bildschirmfenster  *)
                                                      (* <> Amiga-Fenster ! *)	
VAR
	t : REAL;
BEGIN
	sxleft:=sxlti;
	sxrt  :=sxrti;
	sybot :=syboti;
	sytop :=sytopi;
	t:=sxrt-sxleft;
	IF (sytop - sybot < t) THEN t:=sytop-sybot END;
	IF (t < 0.0001) THEN
	   WriteString('Error during execution !'); WriteLn
	ELSIF ( (xmax-xmin = 0.0) OR (ymax-ymin = 0.0) ) THEN
           WriteString('Error during execution !'); WriteLn
	ELSE 
	   scale[1]:=(xmax-xmin)/(sxrt-sxleft);
	   scale[2]:=(ymax-ymin)/(sytop-sybot)
	END
END swindo;

PROCEDURE rwindo( xmini,xmaxi,ymini,ymaxi : REAL); (* Real-Fenster *)
BEGIN
	xmin:=xmini;
	xmax:=xmaxi;
	ymin:=ymini;
	ymax:=ymaxi;
	swindo( sxleft, sxrt, sybot, sytop )
END rwindo;

PROCEDURE segmnt (x1,y1,x2,y2 : REAL); (* Linie zeichnen *)
BEGIN
	UNIXPlot.line( UnixXY(x1), UnixXY(y1), UnixXY(x2), UnixXY(y2) )
END segmnt;

PROCEDURE InitVector; (* Initialisierung der Vektorgrafik *)
BEGIN
	xmin   :=0.0;
	xmax   :=1.0;
	ymin   :=0.0;
	ymax   :=1.0;
	sxleft :=0.0;
	sxrt   :=1.0;
	sybot  :=0.0;
	sytop  :=1.0;
	chxsz  :=0.0218;
	chysz  :=0.0420;
	chrot  :=0.0;
	scale[1]:=1.0;
	scale[2]:=1.0;
	scale[3]:=1.0;
	scale[4]:=0.0;
	nxchar  :=0;
	nychar  :=0;
	nxline  :=1
END InitVector;	   
	
PROCEDURE point (x,y : REAL);  (* Punkt absolut setzen *)
BEGIN
	IF ( ABS(x) <= 1.0) AND ( ABS(y) <= 1.0) THEN 
          UNIXPlot.point( UnixXY(x), UnixXY(y) ) 
	END
END point;

PROCEDURE posang (angle : REAL) : REAL; (* Winkel innerhalb 0..360 grad *)
BEGIN
	IF ( (angle < 360.0) AND (angle >=0.0) ) THEN
	  RETURN angle
	ELSE 
	  angle:=angle - 360.0*REAL(TRUNC(angle/360.0));
	  IF (angle < 0.0) THEN angle:=angle+360.0 END;
	  RETURN angle
	END
END posang;

PROCEDURE ticend (rmin,rmax,dr : REAL; VAR pr1,pr2 : REAL);
VAR
	r1,r2 : REAL;
BEGIN                             (* Achsenskalierung *)
	r1:=REAL(TRUNC(rmin/dr))*dr;
	r2:=REAL(TRUNC(rmax/dr))*dr;
	IF ( (r1 < 0.0) OR (r2 < 0.0) ) THEN 
	   IF ( (r1 > 0.0) OR (r2 > 0.0) ) THEN 
	      pr1:=r1;
	      pr2:=r2
	   ELSE 
	      IF ( (dr<0.0) AND (r1>rmin) ) THEN r1:=r1+dr END;
	      IF ( (dr>0.0) AND (r2>rmax) ) THEN r2:=r2-dr END
	   END
	ELSE 
	   IF ( (dr>0.0) AND (r1<rmin) ) THEN r1:=r1+dr END;
	   IF ( (dr<0.0) AND (r2<rmax) ) THEN r2:=r2-dr END
	END;
	pr1:=r1;
	pr2:=r2
END ticend;

PROCEDURE dxdy( x1,x2 : REAL; nx : INTEGER; VAR lblnum,lbldec : INTEGER)
                                                                   : REAL; 
VAR
	xlen,dx,dxlog,dxmant,t,ln10 : REAL;
	dxexp : INTEGER;                      (* Zeichenabstand berechnen *)
BEGIN
    ln10:=ln(10.0);
    xlen:=x2-x1;
    IF (xlen = 0.0) THEN 
        WriteString('Error during execution !');
        WriteLn;
	lbldec:=0;
	lblnum:=0;
	RETURN 0.0
    ELSE 
	dx:=ABS( xlen/REAL(nx));
	dxlog:=ln(dx)/ln10;
	dxexp:=TRUNC(dxlog);
	dxmant:=dxlog-REAL(dxexp);
	IF (dxmant <= 0.0) THEN
	  dxexp:=dxexp-1;
	  dxmant:=dxmant+1.0
	END;
	dx:=1.0;
	IF (dxmant > 0.18) THEN
	  dx:=2.0 END;
	IF (dxmant > 0.40) THEN 
	  dx:=5.0 END;
	IF (dxmant > 0.88) THEN
	  dx:=10.0 END;
	dx:=dx*exp( ln10*REAL(dxexp) )*xlen/ABS( xlen );
	dxlog:=xlen;
	IF (x1 <> 0.0) THEN 
	  t:= ABS(x1);
	  IF (t > dxlog) THEN dxlog:=t END
	END;
	IF (x2 <> 0.0) THEN 
	  t:=ABS(x2);
	  IF (t > dxlog) THEN dxlog:=t END
	END;
	dxlog:=ln(dxlog)/ln10;
	IF ( dxlog > 0.0) THEN
	  lblnum:=TRUNC(dxlog+1.0)
	ELSE
	  lblnum:=0
        END;
	dxlog:=ABS(xlen);
	IF (x1 <> 0.0) THEN 
	  t:=ABS(x1);
	  IF (t < dxlog) THEN dxlog:=t END
	END;
	IF (x2 <> 0.0) THEN 
	  t:=ABS(x2);
	  IF (t < dxlog) THEN dxlog:=t END
	END;
	t:=ABS(dx);
	IF (t < dxlog) THEN dxlog:=t END;
	dxlog:=ln(dxlog)/ln10;
	IF (dxlog < 0.0) THEN
	  lbldec:=TRUNC(-dxlog+1.0)
	ELSE
	  lbldec:=0
        END;
	lblnum:=lblnum + lbldec +2;
	RETURN dx
    END
END dxdy;

PROCEDURE axis( r1,r2,dri,sx1,sy1,sx2,sy2,ticlen,ticang : REAL;
                lblnum,lbldec : INTEGER; lblang : REAL);
	(* Achsen zeichnen *)
VAR
	angtic,anglbl,lentic,xlen,ylen,rlen,dr,rtic,rend,xtic,ytic,
	angtst,xlabel,ylabel,t,radian,x,y,dtic : REAL;
	alabel : STRING;
        logo : BOOLEAN;
BEGIN
	radian:=57.29578;
	IF ( (dri = 0.0) OR (r2-r1 = 0.0) ) THEN 
	   WriteString('Error during execution !'); WriteLn
	ELSE 
	   IF (lblnum < 7) THEN lblnum:=7 END;
	   IF ( ( (r1<0.0) OR (r2<0.0) ) AND (lblnum < 8) ) THEN lblnum:=8 END;
	   angtic:=ticang;
	   IF (ticlen < 0.0) THEN angtic:= -angtic END;
	   angtic:=posang(angtic);
	   anglbl:=posang(lblang);
	   lentic:=ABS(ticlen);	
	   xlen:=sx2-sx1;
	   ylen:=sy2-sy1;
	   rlen:=r2-r1;
	   dr:=ABS(dri) * ABS(rlen)/rlen;
	   ticend(r1,r2,dr,rtic,rend);
	   angtst:=posang(angtic-anglbl);
	   angtic:=angtic/radian;
	   anglbl:=anglbl/radian;
	   xtic:=lentic*cos(angtic);
	   ytic:=lentic*sin(angtic);
	   scale[3]:=cos(anglbl);
	   scale[4]:=sin(anglbl);
	   IF ( (angtst < 45.0) OR (angtst >= 315.0) ) THEN 
		xlabel:=( chxsz*scale[3] + chysz*scale[4]) /2.0;
 	        ylabel:=(-chysz*scale[3] - chxsz*scale[4])/2.0
	   ELSIF ( angtst < 135.0) THEN 
	        t:=REAL(lblnum-lbldec-1) * chxsz;
	        xlabel:=-t*scale[3] - chysz*scale[4]/2.0;
	        ylabel:=-t*scale[4] + chysz*scale[3]/2.0
	   ELSIF ( angtst < 225.0) THEN
	        t:=(REAL(lblnum)+0.5)*chxsz;
	        xlabel:=-scale[4]*chysz/2.0 - t*scale[3];
	        ylabel:=-scale[3]*chysz/2.0 - t*scale[4]
	   ELSIF ( angtst < 315.0) THEN 
	        t:=REAL(lblnum-lbldec-1)*chxsz;
	        xlabel:=-t*scale[3] + chysz*scale[4]*1.5;
	        ylabel:=-t*scale[4] - chysz*scale[3]*1.5
	   END;
	   segmnt( sx1,sy1, sx2, sy2);
	   WHILE ( (dr<0.0) AND (rtic>=rend) ) OR ( (dr>0.0) AND (rtic<=rend))
	   DO 
	        dtic:=(rtic-r1)/rlen;
	        x:=xlen*dtic+sx1;
	        y:=ylen*dtic+sy1;
	        gmove(x,y);
	        x:=x+xtic;
	        y:=y+ytic;
	        vector(x,y);
	        x:=x+xlabel;
	        y:=y+ylabel;
       	        RealToStr(rtic,alabel,lblnum,lbldec,FALSE,logo);
                gwrite(x,y,alabel);
	        rtic:=rtic+dr
	   END;
	   t:=chrot/radian;
	   scale[3]:=cos(t);
	   scale[4]:=sin(t)
	END
END axis;
	        
PROCEDURE graph1 ( grid : CARDINAL; xmini,xmaxi : REAL; 
                 nx : INTEGER; ymini,ymaxi : REAL; 
	         ny : INTEGER; sxl,sxr,syb,syt : REAL;
                 titel,xcom,ycom : STRING); 
	      (* Koordinatenkreuz zeichnen *)
VAR
	dx,dy,tic,xdot,ydot,dxydot,xydot,ticnd : REAL;	
	lblnum,lbldec : INTEGER;
BEGIN
       chxsz:=0.0218;
       chysz:=0.0420;
       chrot:=0.0;
       xmin:=xmini;
       ymin:=ymini;
       xmax:=xmaxi;
       ymax:=ymaxi;
       swindo(sxl,sxr,syb,syt);
       dx:=dxdy(xmin,xmax,nx,lblnum,lbldec);
       nxchar:=lblnum;
       axis(xmin,xmax,dx,sxl,syb,sxr,syb,0.0148,270.0,lblnum,lbldec,0.0);
       dy:=dxdy(ymin,ymax,ny,lblnum,lbldec);
       nychar:=lblnum;
       axis(ymin,ymax,dy,sxl,syb,sxl,syt,0.0101,180.0,lblnum,lbldec,0.0);
       IF ((grid=2) OR (grid=1)) THEN   
	ticend(xmin,xmax,dx,tic,ticnd);
	dxydot:=dy/5.0;
	IF (tic=xmin) THEN tic:=tic+dx END;
	WHILE ((dx>0.0) AND (tic<=ticnd)) OR ((dx<0.0) AND (tic>=ticnd)) DO
         CASE grid OF 
         1:
      	         xdot:=sx(tic);     (* in vertikaler Richtung Punktraster *)
	         tic:=tic+dx;
	         xydot:=ymin+dxydot;
	         WHILE ((dxydot>0.0) AND (xydot<=ymax)) OR 
	               ((dxydot<0.0) AND (xydot>=ymax)) DO
	            ydot:=sy(xydot);
	            xydot:=xydot + dxydot;
	            point(xdot,ydot)
	         END |
         2:    xdot:=sx(tic);    (* geschlossenes Raster vertikal *)
                 tic:=tic+dx;
                 ydot:=sy(ymin);
                 gmove(xdot,ydot);
                 ydot:=sy(ymax);
                 vector(xdot,ydot)         
         END; (* CASE *)        
	END;
	ticend(ymin,ymax,dy,tic,ticnd);
	dxydot:=dx/5.0;
	IF (tic=ymin) THEN tic:=tic+dy END;
	WHILE ((dy>0.0) AND (tic<=ticnd)) OR ((dy<0.0) AND (tic>=ticnd)) DO
         CASE grid OF
         1:            (* horizontale Linie mit Punkten *)
       	         ydot:=sy(tic);
	         tic:=tic+dy;
	         xydot:=xmin+dxydot;
	         WHILE ((dxydot>0.0) AND (xydot<=xmax)) OR
	               ((dxydot<0.0) AND (xydot>=xmax)) DO
	            xdot:=sx(xydot);
	            xydot:=xydot+dxydot;
	            point(xdot,ydot)
	         END |
         2:    ydot:=sy(tic);  (* geschlossene Raster horizontal *)
                 tic:=tic+dy;    
                 xdot:=sx(xmin);
                 gmove(xdot,ydot);
                 xdot:=sx(xmax);
                 vector(xdot,ydot)  
         END (* CASE *)        
       	END
       END; 
       gwrite(sxl,syt+0.02,titel);
       gwrite(sxl,syb-0.125,xcom);
       ChSet(1.5*chxsz,0.6674*chysz,90.0);
       gwrite(sxl-0.12,syb,ycom)
END graph1;
	
PROCEDURE sxlog (rx : REAL) : REAL;
BEGIN
	RETURN sx(log(ABS(rx))) 	
END sxlog;

PROCEDURE sylog (ry : REAL) : REAL;
BEGIN
	RETURN sy(20.0*log(ABS(ry)))
END sylog;

PROCEDURE logstep (x,logst : REAL) : REAL;
BEGIN
	RETURN PwrOfTen(log(ABS(x))+ABS(logst))
END logstep;

PROCEDURE linstep (x,linst : REAL) : REAL;
BEGIN
	RETURN x+linst
END linstep;

PROCEDURE graph2 ( grid : CARDINAL; xanf, xende, yanf, yende : REAL;
                   ny : INTEGER;
                   sxl,sxr,syb,syt : REAL;
                   titel,xcom,ycom : STRING);
VAR	
	ydot, dx,dy,tic,ticnd,xdot : REAL;
        lblnum, lbldec, nx, i,j : INTEGER;
        grid2 : CARDINAL;
BEGIN
       xanf :=log(ABS(xanf ));
       xende:=log(ABS(xende));
       nx:=ABS( TRUNC(xende)-TRUNC(xanf)); (* Anzahl der Intervalle *)
       IF grid=3 THEN grid2:=2 
       ELSIF grid=2 THEN grid2:=2  
       ELSE grid2:=0 END;
       graph1( grid2, xanf, xende, nx, yanf, yende, ny, sxl, sxr, syb, syt,
                titel,xcom,ycom);  
        dx:=dxdy(xanf, xende, nx, lblnum, lbldec);
        ticend(xanf, xende, dx, tic, ticnd);
        FOR j:=1 TO nx DO
          FOR i:=1 TO 9 DO
            xdot:=sx(tic+log(REAL(i)));
            ydot:=sy(yanf)-0.01;
            gmove(xdot,ydot);
            IF grid=2 THEN
              IF NOT ODD(i) THEN
                 ydot:=sy(yende)
              ELSE
                 ydot:=sy(yanf)
              END
            ELSE
              ydot:=sy(yanf)
            END;  
            vector(xdot,ydot)
          END;
	  tic:=tic+dx
        END
END graph2;

END GraphicLib.	   
