home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
1990
/
10
/
ldm
/
pgraph.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1990-09-06
|
14KB
|
418 lines
UNIT PGRAPH;
INTERFACE
USES Crt,Graph;
CONST
{$IFDEF CPU87} MaxInt=2147483647; {$ENDIF}
nmax=200;
CONST
Black:BYTE=0; Blue:BYTE=1; Green:BYTE=2; Cyan:BYTE=3;
Red:BYTE=4; Magenta:BYTE=5; Brown:BYTE=6; LightGray:BYTE=7;
DarkGray:BYTE=8; LightBlue:BYTE=9; LightGreen:BYTE=10; LightCyan:BYTE=11;
LightRed:BYTE=12; LightMagenta:BYTE=13; Yellow:BYTE=14; White:BYTE=15;
TYPE
{$IFDEF CPU87} REAL=EXTENDED; {$ELSE}
DOUBLE=REAL; SINGLE=REAL; EXTENDED=REAL; COMP=REAL; {$ENDIF}
GeraetTyp = (Bildschirm,Drucker,Plotter);
Vektor = ARRAY[1..nmax] OF REAL;
strg80 = STRING[80];
VAR
Geraet:GeraetTyp; { fuer AngleTrueScale }
GraphDriver,GraphMode,ErrorCode:INTEGER;
OldExitProc:Pointer;
Xaxmin,Xaxmax,Yaxmin,Yaxmax:REAL; { fuer USCALE }
Uaxmin,Uaxmax,Vaxmin,Vaxmax:INTEGER; { fuer Graphikwindow }
PROCEDURE AngleTrueScale(VAR x1,x2,y1,y2:REAL);
PROCEDURE CloseGraphik;
PROCEDURE Curve(VAR x,y:Vektor; n,Lintyp,Thickness,Color:WORD);
PROCEDURE Curvex(VAR x,y:Vektor; n:WORD; Color:BYTE);
FUNCTION EXP10(x:REAL):REAL;
FUNCTION Exponent(x:REAL):INTEGER;
PROCEDURE Extrema(z:Vektor; n:WORD; VAR zmin,zmax:REAL);
PROCEDURE GraphikText(Text:strg80; Font, Size, TxtCol, Line:BYTE);
PROCEDURE GraphikWindow(x1,x2,y1,y2:INTEGER);
PROCEDURE LinaxScale(VAR a,b,dx,Ex:REAL; Density:BYTE; VAR ExpStrg:strg80);
FUNCTION LOG10(x:REAL):REAL;
PROCEDURE LogXAxis(LogX1,LogX2:REAL; XText:strg80; Font,Size:WORD);
PROCEDURE LogYAxis(LogY1,LogY2:REAL; YText:strg80; Font,Size:WORD);
PROCEDURE OpenGraphik;
FUNCTION RealToString(x:REAL):strg80;
PROCEDURE Scale(x,y:REAL; VAR u,v:INTEGER);
PROCEDURE Uscale(VAR x1,x2,y1,y2:REAL; Origin,AngleTrue:BOOLEAN; Expans:REAL);
PROCEDURE XAxis(x1,x2:REAL; XText:strg80; Font,Size:WORD);
PROCEDURE Xgrid(x:REAL);
PROCEDURE Xmark(x:REAL; VAR u:INTEGER; Len:BYTE);
PROCEDURE YAxis(y1,y2:REAL; YText:strg80; Font,Size:WORD);
PROCEDURE Ymark(y:REAL; VAR v:INTEGER; Len:BYTE);
PROCEDURE Ygrid(y:REAL);
IMPLEMENTATION
PROCEDURE AngleTrueScale; { Winkeltreue Skalierung }
VAR C,dx,dy,xx,yy,xm,ym,F:REAL; Xasp,Yasp:WORD;
BEGIN
IF Geraet=Bildschirm THEN BEGIN { Laenge/Breite-Faktor }
GetAspectRatio(Xasp,Yasp);
F:=(Xasp/Yasp)*(Abs(Uaxmin-Uaxmax)/Abs(Vaxmin-Vaxmax)); END
ELSE BEGIN
F:=(2/3)*(Abs(Uaxmin-Uaxmax)/Abs(Vaxmin-Vaxmax))
END;
dx:=Abs(x2-x1);
dy:=Abs(y2-y1);
IF dx>=dy THEN BEGIN
yy:=0.5*dx/F; IF y1>y2 THEN yy:=-yy; { y-Achse strecken }
ym:=0.5*(y1+y2); y1:=ym-yy; y2:=ym+yy; END
ELSE BEGIN
xx:=0.5*dy*F; IF x1>x2 THEN xx:=-xx; { x-Achse strecken }
xm:=0.5*(x1+x2); x1:=xm-xx; x2:=xm+xx;
END;
END;
{$F+} PROCEDURE CloseGraphik; { Graphik beenden }
BEGIN
ExitProc:=OldExitProc;
SetBkColor(Black);
CloseGraph;
DirectVideo:=TRUE;
Window(1,1,80,25);
END; {$F-}
PROCEDURE Curve; { Polygonzug }
VAR i,u1,v1,u2,v2:INTEGER;
BEGIN
SetLineStyle(Lintyp,0,Thickness); SetColor(Color);
Scale(x[1],y[1],u1,v1);
FOR i:=2 TO n DO BEGIN
Scale(x[i],y[i],u2,v2); Line(u1,v1,u2,v2);
u1:=u2; v1:=v2;
END;
END;
PROCEDURE Curvex; { Punkte auftragen }
VAR i,u,v:INTEGER;
BEGIN
FOR i:=1 TO n DO BEGIN
Scale(x[i],y[i],u,v); PutPixel(u,v,Color);
END;
END;
FUNCTION EXP10;
VAR S:STRING[80]; E:REAL; Code:WORD;
BEGIN
IF x=Int(x) THEN BEGIN { 10 hoch Integer }
Str(Trunc(x),S);
Val(('1.0E'+S),E,Code); EXP10:=E; Exit;
END;
EXP10:=Exp(x*Ln(10)); { 10 hoch Real }
END;
FUNCTION Exponent; { Groessenordnung }
VAR Ex,S:STRING[80]; n,Code:INTEGER; { einer Zahl }
BEGIN
Str(x,S); Ex:=Copy(S,Pos('E',S)+1,Length(S));
Val(Ex,n,Code); Exponent:=n;
END;
PROCEDURE Extrema; { Maximum und Minimum }
VAR i:WORD; { des Vektors z[1..n] }
BEGIN
zmin:=z[1]; zmax:=z[1];
FOR i:=2 TO n DO BEGIN
IF z[i]<zmin THEN zmin:=z[i];
IF z[i]>zmax THEN zmax:=z[i];
END;
END;
PROCEDURE GraphikText; { Textausgabe ins }
VAR Xpos,Ypos:INTEGER; { Graphikfenster }
BEGIN
IF (Font>4) OR (Font<0) THEN Font:=1;
IF (Size>10) OR (Size<1) THEN Size:=1;
IF (Line>24) THEN Line:=24; { Zeile 1..24 }
IF (Line<1) THEN Line:=1;
IF Font=2 THEN Size:=Size*2;
SetViewPort(0,0,GetMaxX,GetMaxY,ClipOn);
SetColor(TxtCol);
SetTextStyle(Font,HorizDir,Size);
SetTextJustify(CenterText,CenterText); { Zentrieren }
Xpos:=Succ(GetMaxX) DIV 2;
Ypos:=Line*(GetMaxY DIV 25);
OutTextXY(Xpos,Ypos,Text);
END;
PROCEDURE GraphikWindow; { Graphikfenster }
VAR h:INTEGER;
BEGIN
SetLineStyle(SolidLn,0,NormWidth); SetColor(White);
IF x1>x2 THEN BEGIN h:=x1; x1:=x2; x2:=h; END;
IF y1>y2 THEN BEGIN h:=y1; y1:=y2; y2:=h; END;
Line(x1,GetMaxY-y1,x2,GetMaxY-y1); { Rahmen }
Line(x2,GetMaxY-y1,x2,GetMaxY-y2);
Line(x2,GetMaxY-y2,x1,GetMaxY-y2);
Line(x1,GetMaxY-y2,x1,GetMaxY-y1);
Uaxmin:=x1; Uaxmax:=x2; Vaxmin:=y1; Vaxmax:=y2; { Fensterkoordinaten }
END;
PROCEDURE LinaxScale; { Hilfsroutine fuer }
VAR x1,x2:REAL; { Xaxis und Yaxis }
BEGIN
IF Abs(a)<Abs(b) THEN Ex:=Exponent(b) ELSE Ex:=Exponent(a);
x1:=a; x2:=b; dx:=0.25*EXP10(Exponent(b-a));
ExpStrg:='0';
IF Abs(Ex)>3 THEN BEGIN { Exponent abtrennen }
a:=a*EXP10(-Ex); b:=b*EXP10(-Ex); dx:=dx*EXP10(-Ex);
Str(Ex:4:0,ExpStrg); WHILE ExpStrg[1]=#32 DO Delete(ExpStrg,1,1);
END;
WHILE ((b-a)/dx)>=Density DO dx:=2*dx; { Skalendichte }
IF b<a THEN dx:=-dx;
IF a=b THEN BEGIN a:=a-dx; b:=b+dx; END;
a:=dx*Round(a/dx); { Guenstig runden }
b:=dx*Round(b/dx);
IF a<b THEN BEGIN
IF a<x1 THEN a:=a+dx; IF b>x2 THEN b:=b-dx; END
ELSE BEGIN
IF a>x1 THEN a:=a-dx; IF b<x2 THEN b:=b+dx;
END;
END;
FUNCTION LOG10; { dekad. Logarithmus }
BEGIN
IF x<>0 THEN LOG10:=Ln(Abs(x))/Ln(10.0) ELSE LOG10:=0;
END;
PROCEDURE LogXAxis; { Log. x-Achse }
CONST Density=10; { Skalendichte }
VAR dn,n1,n2,n,k,u,v:INTEGER; x:REAL; S:STRING[6];
BEGIN
Line(Uaxmin,GetMaxY-Vaxmin,Uaxmax,GetMaxY-Vaxmin);
u:=(Uaxmax+Uaxmin) DIV 2;
v:=GetMaxY-(Vaxmin-3*TextHeight(XText));
SetTextStyle(Font,HorizDir,Size);
SetTextJustify(CenterText,CenterText);
OutTextXY(u,v,XText); { Achsenbeschriftung }
n1:=Trunc(LogX1); n2:=Trunc(LogX2);
IF n1>n2 THEN BEGIN k:=n1; n1:=n2; n2:=k; END;
dn:=1; WHILE (n2-n1) DIV dn>=Density DO dn:=Density*dn;
IF dn=1 THEN BEGIN { Log-Skala }
FOR n:=n1-1 TO n2+1 DO
FOR k:=2 TO 9 DO BEGIN x:=n+LOG10(k); Xmark(x,u,3); END;
END;
FOR n:=n1 TO n2 DO BEGIN
IF (dn<>1) AND ((n MOD (dn DIV 10))=0) THEN Xmark(n,u,3);
IF (n MOD dn)=0 THEN BEGIN
Xmark(n,u,4);
Str(n,S);
OutTextXY(u+TextWidth(S)*4 DIV 5,GetMaxY-Vaxmin+(TextHeight('0') DIV 2),S);
OutTextXY(u-TextWidth('0') DIV 2,GetMaxY-Vaxmin+TextHeight('0'),'10');
END;
END;
END;
PROCEDURE LogYAxis; { log. y-Achse }
CONST Density=10; { Skalendichte }
VAR dn,n1,n2,n,k,u,v:INTEGER; y:REAL; S:STRING[6];
BEGIN
Line(Uaxmin,GetMaxY-Vaxmin,Uaxmin,GetMaxY-Vaxmax);
u:=Uaxmin-3*TextHeight(YText);
v:=(Vaxmax-Vaxmin) DIV 2;
SetTextStyle(Font,VertDir,Size);
SetTextJustify(CenterText,CenterText);
OutTextXY(u,v,YText); { Achsenbeschriftung }
n1:=Trunc(LogY1); n2:=Trunc(LogY2);
IF n1>n2 THEN BEGIN k:=n1; n1:=n2; n2:=k; END;
dn:=1; WHILE (n2-n1) DIV dn>=Density DO dn:=Density*dn;
IF dn=1 THEN BEGIN { Log-Skala }
FOR n:=n1-1 TO n2+1 DO
FOR k:=2 TO 9 DO BEGIN y:=n+LOG10(k); Ymark(y,v,3); END;
END;
FOR n:=n1 TO n2 DO BEGIN
IF (dn<>1) AND ((n MOD (dn DIV 10))=0) THEN Ymark(n,u,3);
IF (n MOD dn)=0 THEN BEGIN
Ymark(n,v,4);
Str(n,S);
OutTextXY(Uaxmin-TextHeight('0'),v-TextWidth(S)*3 DIV 4,S);
OutTextXY(Uaxmin-TextHeight('0') DIV 2,v+TextWidth('0') DIV 2,'10');
END;
END;
END;
PROCEDURE OpenGraphik; { Graphik starten }
BEGIN
DirectVideo:=FALSE; { Graphik- und Textmode }
OldExitProc:=ExitProc; ExitProc:=Addr(CloseGraphik);
GraphDriver:=Detect;
InitGraph(GraphDriver,GraphMode,'');
ErrorCode:=GraphResult;
IF ErrorCode<>grOk THEN BEGIN
WriteLn('Graphics error: ',GraphErrorMsg(ErrorCode)); ReadLn;
Halt(1);
END;
IF GraphDriver=7 THEN BEGIN
Black:=0; Blue:=15; Green:=15; Cyan:=15;
Red:=15; Magenta:=15; Brown:=15; LightGray:=15;
DarkGray:=15; LightBlue:=15; LightGreen:=15; LightCyan:=15;
LightRed:=15; LightMagenta:=15; Yellow:=15; White:=15;
END;
IF Geraet IN [Bildschirm,Drucker,Plotter] THEN ELSE Geraet:=Drucker;
Uaxmin:=0; Uaxmax:=GetMaxX; Vaxmin:=0; Vaxmax:=GetMaxY;
END;
FUNCTION RealToString; { Reelle Zahl in }
VAR S:strg80; Code:WORD; { handlichen String }
BEGIN
Str(x:16:10,S);
WHILE S[1]=#32 DO Delete(S,1,1);
WHILE S[Length(S)]='0' DO BEGIN Delete(S,Length(S),1); END;
IF Pos('.',S)=Length(S) THEN Delete(S,Length(S),1);
Val(S,x,Code); IF x=0 THEN S:='0';
RealToString:=S;
END;
PROCEDURE Scale; { Absolute Skalierung }
BEGIN
u:= Uaxmin+Round((x-Xaxmin)/(Xaxmax-Xaxmin)*(Uaxmax-Uaxmin));
v:=GetMaxY-Round((y-Yaxmin)/(Yaxmax-Yaxmin)*(Vaxmax-Vaxmin))-Vaxmin;
END;
PROCEDURE Uscale; { Benutzer- }
VAR xx,yy:REAL; { koordinatensystem }
CONST Tol = 0.01;
BEGIN
Expans:=Abs(Expans);
xx:=Abs(x2-x1)*0.005*Expans; IF x1>x2 THEN xx:=-xx; { 1. Ausweiten }
x1:=x1-xx; x2:=x2+xx;
IF Abs(x2-x1)<1E-8 THEN
BEGIN x1:=x1*(1-0.01*Expans); x2:=x2*(1+0.01*Expans); END;
yy:=Abs(y2-y1)*0.005*Expans; IF y1>y2 THEN yy:=-yy;
y1:=y1-yy; y2:=y2+yy;
IF Abs(y2-y1)<1E-8 THEN
BEGIN y1:=y1*(1-0.01*Expans); y2:=y2*(1+0.01*Expans); END;
IF Origin THEN BEGIN { 2. Ursprung }
IF x1<=x2 THEN BEGIN
IF x2<0 THEN x2:=0;
IF x1>0 THEN x1:=0; END
ELSE BEGIN
IF x2>0 THEN x2:=0;
IF x1<0 THEN x1:=0;
END;
IF y1<=y2 THEN BEGIN
IF y2<0 THEN y2:=0;
IF y1>0 THEN y1:=0; END
ELSE BEGIN
IF y2>0 THEN y2:=0;
IF y1<0 THEN y1:=0;
END;
END;
IF AngleTrue THEN AngleTrueScale(x1,x2,y1,y2); { 3. Winkeltreue }
IF Abs((x2-x1)/x2)<Tol THEN BEGIN { 4. Minimalausdehnung }
IF x1<x2 THEN
BEGIN x1:=x1*(1-Tol); x2:=x2*(1+Tol); END
ELSE BEGIN x2:=x2*(1-Tol); x1:=x1*(1+Tol); END;
END;
IF Abs((y2-y1)/y2)<Tol THEN BEGIN
IF y1<y2 THEN
BEGIN y1:=y1*(1-Tol); y2:=y2*(1+Tol); END
ELSE BEGIN y2:=y2*(1-Tol); y1:=y1*(1+Tol); END;
END;
Xaxmin:=x1; Xaxmax:=x2;
Yaxmin:=y1; Yaxmax:=y2;
END;
PROCEDURE XAxis; { lineare x-Achse }
VAR Xpos,Ypos:INTEGER;
Ex,u,v,a,b,x,dx,h:REAL; E,S:strg80;
CONST Density=6; { Skalendichte }
BEGIN
Line(Uaxmin,GetMaxY-Vaxmin,Uaxmax,GetMaxY-Vaxmin);
Xpos:=(Uaxmax+Uaxmin) DIV 2;
Ypos:=GetMaxY-(Vaxmin-3*TextHeight(XText));
a:=x1; b:=x2; IF a>b THEN BEGIN h:=b; b:=a; a:=b; END;
LinaxScale(x1,x2,dx,Ex,Density,E);
IF x1>x2 THEN BEGIN h:=x1; x1:=x2; x2:=h; dx:=Abs(dx); END;
SetTextStyle(Font,HorizDir,Size);
SetTextJustify(CenterText,CenterText);
IF E='0' THEN { Achsenbeschriftung }
OutTextXY(Xpos,Ypos,XText)
ELSE BEGIN
u:=Xaxmin; v:=Xaxmax;
OutTextXY(Xpos,Ypos,XText+' *E'+E);
a:=a*EXP10(-Ex); b:=b*EXP10(-Ex); Xaxmin:=a; Xaxmax:=b;
END;
x:=x1; { lineare Skala }
Xmark(x-dx/2,Xpos,3);
REPEAT
Xmark(x+dx/2,Xpos,3);
Xmark(x,Xpos,3);
S:=RealToString(x);
Line(Xpos,GetMaxY-Vaxmin,Xpos,GetMaxY-Vaxmin-3);
IF Length(S)<6 THEN OutTextXY(Xpos,GetMaxY-Vaxmin+TextHeight('0'),S);
x:=x+dx;
UNTIL (x>=b) OR (x<=a);
IF E<>'0' THEN BEGIN Xaxmin:=u; Xaxmax:=v; END;
END;
PROCEDURE Xgrid; { Parallele zur }
VAR u,v:INTEGER; { x-Achse }
BEGIN
Scale(x,0,u,v);
IF u>Uaxmin THEN Line(u,GetMaxY-Vaxmin,u,GetMaxY-Vaxmax);
END;
PROCEDURE Xmark; { x-Achsenmarken: }
VAR v:INTEGER; { Hilfsroutine fuer }
BEGIN { Xaxis und LogXAxis }
Scale(x,Yaxmin,u,v);
IF (u>=Uaxmin) AND (u<=Uaxmax) THEN
Line(u,GetMaxY-Vaxmin,u,GetMaxY-Vaxmin-Len);
END;
PROCEDURE YAxis; { lineare y-Achse }
VAR Xpos,Ypos:INTEGER;
Ex,u,v,a,b,y,dy,h:REAL; E,S:strg80;
CONST Density=8; { Skalendichte }
BEGIN
Line(Uaxmin,GetMaxY-Vaxmin,Uaxmin,GetMaxY-Vaxmax);
Xpos:=Uaxmin-3*TextHeight(YText);
Ypos:=(Vaxmax-Vaxmin) DIV 2;
a:=y1; b:=y2; IF a>b THEN BEGIN h:=b; b:=a; a:=b; END;
LinaxScale(y1,y2,dy,Ex,Density,E);
IF y1>y2 THEN BEGIN h:=y1; y1:=y2; y2:=h; dy:=Abs(dy); END;
SetTextStyle(Font,VertDir,Size);
SetTextJustify(CenterText,CenterText);
IF E='0' THEN { Achsenbeschriftung }
OutTextXY(Xpos,Ypos,YText)
ELSE BEGIN
u:=Yaxmin; v:=Yaxmax;
OutTextXY(Xpos,Ypos,YText+' *E'+E);
a:=a*EXP10(-Ex); b:=b*EXP10(-Ex); Yaxmin:=a; Yaxmax:=b;
END;
y:=y1; { lineare Skala }
Ymark(y-dy/2,Ypos,3);
REPEAT
Ymark(y+dy/2,Ypos,3);
S:=RealToString(y);
Ymark(y,Ypos,3);
IF Length(S)<6 THEN OutTextXY(Uaxmin-TextHeight('0'),Ypos,S);
y:=y+dy;
UNTIL (y>=b) OR (y<=a);
IF E<>'0' THEN BEGIN Yaxmin:=u; Yaxmax:=v; END;
END;
PROCEDURE Ygrid; { Parallele zur }
VAR u,v:INTEGER; { y-Achse }
BEGIN
Scale(0,y,u,v);
IF v<GetMaxY-Vaxmin THEN Line(Uaxmin,v,Uaxmax,v);
END;
PROCEDURE Ymark; { y-Achsenmarken: }
VAR u:INTEGER; { Hilfsroutine fuer }
BEGIN { Yaxis und LogYAxis }
Scale(Xaxmin,y,u,v);
IF (v<GetMaxY-Vaxmin) AND (v>GetMaxY-Vaxmax) THEN
Line(Uaxmin,v,Uaxmin+Len,v);
END;
END.